LLVM API Documentation
00001 //===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements a coalescing interval map for small objects. 00011 // 00012 // KeyT objects are mapped to ValT objects. Intervals of keys that map to the 00013 // same value are represented in a compressed form. 00014 // 00015 // Iterators provide ordered access to the compressed intervals rather than the 00016 // individual keys, and insert and erase operations use key intervals as well. 00017 // 00018 // Like SmallVector, IntervalMap will store the first N intervals in the map 00019 // object itself without any allocations. When space is exhausted it switches to 00020 // a B+-tree representation with very small overhead for small key and value 00021 // objects. 00022 // 00023 // A Traits class specifies how keys are compared. It also allows IntervalMap to 00024 // work with both closed and half-open intervals. 00025 // 00026 // Keys and values are not stored next to each other in a std::pair, so we don't 00027 // provide such a value_type. Dereferencing iterators only returns the mapped 00028 // value. The interval bounds are accessible through the start() and stop() 00029 // iterator methods. 00030 // 00031 // IntervalMap is optimized for small key and value objects, 4 or 8 bytes each 00032 // is the optimal size. For large objects use std::map instead. 00033 // 00034 //===----------------------------------------------------------------------===// 00035 // 00036 // Synopsis: 00037 // 00038 // template <typename KeyT, typename ValT, unsigned N, typename Traits> 00039 // class IntervalMap { 00040 // public: 00041 // typedef KeyT key_type; 00042 // typedef ValT mapped_type; 00043 // typedef RecyclingAllocator<...> Allocator; 00044 // class iterator; 00045 // class const_iterator; 00046 // 00047 // explicit IntervalMap(Allocator&); 00048 // ~IntervalMap(): 00049 // 00050 // bool empty() const; 00051 // KeyT start() const; 00052 // KeyT stop() const; 00053 // ValT lookup(KeyT x, Value NotFound = Value()) const; 00054 // 00055 // const_iterator begin() const; 00056 // const_iterator end() const; 00057 // iterator begin(); 00058 // iterator end(); 00059 // const_iterator find(KeyT x) const; 00060 // iterator find(KeyT x); 00061 // 00062 // void insert(KeyT a, KeyT b, ValT y); 00063 // void clear(); 00064 // }; 00065 // 00066 // template <typename KeyT, typename ValT, unsigned N, typename Traits> 00067 // class IntervalMap::const_iterator : 00068 // public std::iterator<std::bidirectional_iterator_tag, ValT> { 00069 // public: 00070 // bool operator==(const const_iterator &) const; 00071 // bool operator!=(const const_iterator &) const; 00072 // bool valid() const; 00073 // 00074 // const KeyT &start() const; 00075 // const KeyT &stop() const; 00076 // const ValT &value() const; 00077 // const ValT &operator*() const; 00078 // const ValT *operator->() const; 00079 // 00080 // const_iterator &operator++(); 00081 // const_iterator &operator++(int); 00082 // const_iterator &operator--(); 00083 // const_iterator &operator--(int); 00084 // void goToBegin(); 00085 // void goToEnd(); 00086 // void find(KeyT x); 00087 // void advanceTo(KeyT x); 00088 // }; 00089 // 00090 // template <typename KeyT, typename ValT, unsigned N, typename Traits> 00091 // class IntervalMap::iterator : public const_iterator { 00092 // public: 00093 // void insert(KeyT a, KeyT b, Value y); 00094 // void erase(); 00095 // }; 00096 // 00097 //===----------------------------------------------------------------------===// 00098 00099 #ifndef LLVM_ADT_INTERVALMAP_H 00100 #define LLVM_ADT_INTERVALMAP_H 00101 00102 #include "llvm/ADT/PointerIntPair.h" 00103 #include "llvm/ADT/SmallVector.h" 00104 #include "llvm/Support/Allocator.h" 00105 #include "llvm/Support/RecyclingAllocator.h" 00106 #include <iterator> 00107 00108 namespace llvm { 00109 00110 00111 //===----------------------------------------------------------------------===// 00112 //--- Key traits ---// 00113 //===----------------------------------------------------------------------===// 00114 // 00115 // The IntervalMap works with closed or half-open intervals. 00116 // Adjacent intervals that map to the same value are coalesced. 00117 // 00118 // The IntervalMapInfo traits class is used to determine if a key is contained 00119 // in an interval, and if two intervals are adjacent so they can be coalesced. 00120 // The provided implementation works for closed integer intervals, other keys 00121 // probably need a specialized version. 00122 // 00123 // The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x). 00124 // 00125 // It is assumed that (a;b] half-open intervals are not used, only [a;b) is 00126 // allowed. This is so that stopLess(a, b) can be used to determine if two 00127 // intervals overlap. 00128 // 00129 //===----------------------------------------------------------------------===// 00130 00131 template <typename T> 00132 struct IntervalMapInfo { 00133 00134 /// startLess - Return true if x is not in [a;b]. 00135 /// This is x < a both for closed intervals and for [a;b) half-open intervals. 00136 static inline bool startLess(const T &x, const T &a) { 00137 return x < a; 00138 } 00139 00140 /// stopLess - Return true if x is not in [a;b]. 00141 /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals. 00142 static inline bool stopLess(const T &b, const T &x) { 00143 return b < x; 00144 } 00145 00146 /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce. 00147 /// This is a+1 == b for closed intervals, a == b for half-open intervals. 00148 static inline bool adjacent(const T &a, const T &b) { 00149 return a+1 == b; 00150 } 00151 00152 }; 00153 00154 template <typename T> 00155 struct IntervalMapHalfOpenInfo { 00156 00157 /// startLess - Return true if x is not in [a;b). 00158 static inline bool startLess(const T &x, const T &a) { 00159 return x < a; 00160 } 00161 00162 /// stopLess - Return true if x is not in [a;b). 00163 static inline bool stopLess(const T &b, const T &x) { 00164 return b <= x; 00165 } 00166 00167 /// adjacent - Return true when the intervals [x;a) and [b;y) can coalesce. 00168 static inline bool adjacent(const T &a, const T &b) { 00169 return a == b; 00170 } 00171 00172 }; 00173 00174 /// IntervalMapImpl - Namespace used for IntervalMap implementation details. 00175 /// It should be considered private to the implementation. 00176 namespace IntervalMapImpl { 00177 00178 // Forward declarations. 00179 template <typename, typename, unsigned, typename> class LeafNode; 00180 template <typename, typename, unsigned, typename> class BranchNode; 00181 00182 typedef std::pair<unsigned,unsigned> IdxPair; 00183 00184 00185 //===----------------------------------------------------------------------===// 00186 //--- IntervalMapImpl::NodeBase ---// 00187 //===----------------------------------------------------------------------===// 00188 // 00189 // Both leaf and branch nodes store vectors of pairs. 00190 // Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT). 00191 // 00192 // Keys and values are stored in separate arrays to avoid padding caused by 00193 // different object alignments. This also helps improve locality of reference 00194 // when searching the keys. 00195 // 00196 // The nodes don't know how many elements they contain - that information is 00197 // stored elsewhere. Omitting the size field prevents padding and allows a node 00198 // to fill the allocated cache lines completely. 00199 // 00200 // These are typical key and value sizes, the node branching factor (N), and 00201 // wasted space when nodes are sized to fit in three cache lines (192 bytes): 00202 // 00203 // T1 T2 N Waste Used by 00204 // 4 4 24 0 Branch<4> (32-bit pointers) 00205 // 8 4 16 0 Leaf<4,4>, Branch<4> 00206 // 8 8 12 0 Leaf<4,8>, Branch<8> 00207 // 16 4 9 12 Leaf<8,4> 00208 // 16 8 8 0 Leaf<8,8> 00209 // 00210 //===----------------------------------------------------------------------===// 00211 00212 template <typename T1, typename T2, unsigned N> 00213 class NodeBase { 00214 public: 00215 enum { Capacity = N }; 00216 00217 T1 first[N]; 00218 T2 second[N]; 00219 00220 /// copy - Copy elements from another node. 00221 /// @param Other Node elements are copied from. 00222 /// @param i Beginning of the source range in other. 00223 /// @param j Beginning of the destination range in this. 00224 /// @param Count Number of elements to copy. 00225 template <unsigned M> 00226 void copy(const NodeBase<T1, T2, M> &Other, unsigned i, 00227 unsigned j, unsigned Count) { 00228 assert(i + Count <= M && "Invalid source range"); 00229 assert(j + Count <= N && "Invalid dest range"); 00230 for (unsigned e = i + Count; i != e; ++i, ++j) { 00231 first[j] = Other.first[i]; 00232 second[j] = Other.second[i]; 00233 } 00234 } 00235 00236 /// moveLeft - Move elements to the left. 00237 /// @param i Beginning of the source range. 00238 /// @param j Beginning of the destination range. 00239 /// @param Count Number of elements to copy. 00240 void moveLeft(unsigned i, unsigned j, unsigned Count) { 00241 assert(j <= i && "Use moveRight shift elements right"); 00242 copy(*this, i, j, Count); 00243 } 00244 00245 /// moveRight - Move elements to the right. 00246 /// @param i Beginning of the source range. 00247 /// @param j Beginning of the destination range. 00248 /// @param Count Number of elements to copy. 00249 void moveRight(unsigned i, unsigned j, unsigned Count) { 00250 assert(i <= j && "Use moveLeft shift elements left"); 00251 assert(j + Count <= N && "Invalid range"); 00252 while (Count--) { 00253 first[j + Count] = first[i + Count]; 00254 second[j + Count] = second[i + Count]; 00255 } 00256 } 00257 00258 /// erase - Erase elements [i;j). 00259 /// @param i Beginning of the range to erase. 00260 /// @param j End of the range. (Exclusive). 00261 /// @param Size Number of elements in node. 00262 void erase(unsigned i, unsigned j, unsigned Size) { 00263 moveLeft(j, i, Size - j); 00264 } 00265 00266 /// erase - Erase element at i. 00267 /// @param i Index of element to erase. 00268 /// @param Size Number of elements in node. 00269 void erase(unsigned i, unsigned Size) { 00270 erase(i, i+1, Size); 00271 } 00272 00273 /// shift - Shift elements [i;size) 1 position to the right. 00274 /// @param i Beginning of the range to move. 00275 /// @param Size Number of elements in node. 00276 void shift(unsigned i, unsigned Size) { 00277 moveRight(i, i + 1, Size - i); 00278 } 00279 00280 /// transferToLeftSib - Transfer elements to a left sibling node. 00281 /// @param Size Number of elements in this. 00282 /// @param Sib Left sibling node. 00283 /// @param SSize Number of elements in sib. 00284 /// @param Count Number of elements to transfer. 00285 void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, 00286 unsigned Count) { 00287 Sib.copy(*this, 0, SSize, Count); 00288 erase(0, Count, Size); 00289 } 00290 00291 /// transferToRightSib - Transfer elements to a right sibling node. 00292 /// @param Size Number of elements in this. 00293 /// @param Sib Right sibling node. 00294 /// @param SSize Number of elements in sib. 00295 /// @param Count Number of elements to transfer. 00296 void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, 00297 unsigned Count) { 00298 Sib.moveRight(0, Count, SSize); 00299 Sib.copy(*this, Size-Count, 0, Count); 00300 } 00301 00302 /// adjustFromLeftSib - Adjust the number if elements in this node by moving 00303 /// elements to or from a left sibling node. 00304 /// @param Size Number of elements in this. 00305 /// @param Sib Right sibling node. 00306 /// @param SSize Number of elements in sib. 00307 /// @param Add The number of elements to add to this node, possibly < 0. 00308 /// @return Number of elements added to this node, possibly negative. 00309 int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) { 00310 if (Add > 0) { 00311 // We want to grow, copy from sib. 00312 unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size); 00313 Sib.transferToRightSib(SSize, *this, Size, Count); 00314 return Count; 00315 } else { 00316 // We want to shrink, copy to sib. 00317 unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize); 00318 transferToLeftSib(Size, Sib, SSize, Count); 00319 return -Count; 00320 } 00321 } 00322 }; 00323 00324 /// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes. 00325 /// @param Node Array of pointers to sibling nodes. 00326 /// @param Nodes Number of nodes. 00327 /// @param CurSize Array of current node sizes, will be overwritten. 00328 /// @param NewSize Array of desired node sizes. 00329 template <typename NodeT> 00330 void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, 00331 unsigned CurSize[], const unsigned NewSize[]) { 00332 // Move elements right. 00333 for (int n = Nodes - 1; n; --n) { 00334 if (CurSize[n] == NewSize[n]) 00335 continue; 00336 for (int m = n - 1; m != -1; --m) { 00337 int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m], 00338 NewSize[n] - CurSize[n]); 00339 CurSize[m] -= d; 00340 CurSize[n] += d; 00341 // Keep going if the current node was exhausted. 00342 if (CurSize[n] >= NewSize[n]) 00343 break; 00344 } 00345 } 00346 00347 if (Nodes == 0) 00348 return; 00349 00350 // Move elements left. 00351 for (unsigned n = 0; n != Nodes - 1; ++n) { 00352 if (CurSize[n] == NewSize[n]) 00353 continue; 00354 for (unsigned m = n + 1; m != Nodes; ++m) { 00355 int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n], 00356 CurSize[n] - NewSize[n]); 00357 CurSize[m] += d; 00358 CurSize[n] -= d; 00359 // Keep going if the current node was exhausted. 00360 if (CurSize[n] >= NewSize[n]) 00361 break; 00362 } 00363 } 00364 00365 #ifndef NDEBUG 00366 for (unsigned n = 0; n != Nodes; n++) 00367 assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle"); 00368 #endif 00369 } 00370 00371 /// IntervalMapImpl::distribute - Compute a new distribution of node elements 00372 /// after an overflow or underflow. Reserve space for a new element at Position, 00373 /// and compute the node that will hold Position after redistributing node 00374 /// elements. 00375 /// 00376 /// It is required that 00377 /// 00378 /// Elements == sum(CurSize), and 00379 /// Elements + Grow <= Nodes * Capacity. 00380 /// 00381 /// NewSize[] will be filled in such that: 00382 /// 00383 /// sum(NewSize) == Elements, and 00384 /// NewSize[i] <= Capacity. 00385 /// 00386 /// The returned index is the node where Position will go, so: 00387 /// 00388 /// sum(NewSize[0..idx-1]) <= Position 00389 /// sum(NewSize[0..idx]) >= Position 00390 /// 00391 /// The last equality, sum(NewSize[0..idx]) == Position, can only happen when 00392 /// Grow is set and NewSize[idx] == Capacity-1. The index points to the node 00393 /// before the one holding the Position'th element where there is room for an 00394 /// insertion. 00395 /// 00396 /// @param Nodes The number of nodes. 00397 /// @param Elements Total elements in all nodes. 00398 /// @param Capacity The capacity of each node. 00399 /// @param CurSize Array[Nodes] of current node sizes, or NULL. 00400 /// @param NewSize Array[Nodes] to receive the new node sizes. 00401 /// @param Position Insert position. 00402 /// @param Grow Reserve space for a new element at Position. 00403 /// @return (node, offset) for Position. 00404 IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, 00405 const unsigned *CurSize, unsigned NewSize[], 00406 unsigned Position, bool Grow); 00407 00408 00409 //===----------------------------------------------------------------------===// 00410 //--- IntervalMapImpl::NodeSizer ---// 00411 //===----------------------------------------------------------------------===// 00412 // 00413 // Compute node sizes from key and value types. 00414 // 00415 // The branching factors are chosen to make nodes fit in three cache lines. 00416 // This may not be possible if keys or values are very large. Such large objects 00417 // are handled correctly, but a std::map would probably give better performance. 00418 // 00419 //===----------------------------------------------------------------------===// 00420 00421 enum { 00422 // Cache line size. Most architectures have 32 or 64 byte cache lines. 00423 // We use 64 bytes here because it provides good branching factors. 00424 Log2CacheLine = 6, 00425 CacheLineBytes = 1 << Log2CacheLine, 00426 DesiredNodeBytes = 3 * CacheLineBytes 00427 }; 00428 00429 template <typename KeyT, typename ValT> 00430 struct NodeSizer { 00431 enum { 00432 // Compute the leaf node branching factor that makes a node fit in three 00433 // cache lines. The branching factor must be at least 3, or some B+-tree 00434 // balancing algorithms won't work. 00435 // LeafSize can't be larger than CacheLineBytes. This is required by the 00436 // PointerIntPair used by NodeRef. 00437 DesiredLeafSize = DesiredNodeBytes / 00438 static_cast<unsigned>(2*sizeof(KeyT)+sizeof(ValT)), 00439 MinLeafSize = 3, 00440 LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize 00441 }; 00442 00443 typedef NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize> LeafBase; 00444 00445 enum { 00446 // Now that we have the leaf branching factor, compute the actual allocation 00447 // unit size by rounding up to a whole number of cache lines. 00448 AllocBytes = (sizeof(LeafBase) + CacheLineBytes-1) & ~(CacheLineBytes-1), 00449 00450 // Determine the branching factor for branch nodes. 00451 BranchSize = AllocBytes / 00452 static_cast<unsigned>(sizeof(KeyT) + sizeof(void*)) 00453 }; 00454 00455 /// Allocator - The recycling allocator used for both branch and leaf nodes. 00456 /// This typedef is very likely to be identical for all IntervalMaps with 00457 /// reasonably sized entries, so the same allocator can be shared among 00458 /// different kinds of maps. 00459 typedef RecyclingAllocator<BumpPtrAllocator, char, 00460 AllocBytes, CacheLineBytes> Allocator; 00461 00462 }; 00463 00464 00465 //===----------------------------------------------------------------------===// 00466 //--- IntervalMapImpl::NodeRef ---// 00467 //===----------------------------------------------------------------------===// 00468 // 00469 // B+-tree nodes can be leaves or branches, so we need a polymorphic node 00470 // pointer that can point to both kinds. 00471 // 00472 // All nodes are cache line aligned and the low 6 bits of a node pointer are 00473 // always 0. These bits are used to store the number of elements in the 00474 // referenced node. Besides saving space, placing node sizes in the parents 00475 // allow tree balancing algorithms to run without faulting cache lines for nodes 00476 // that may not need to be modified. 00477 // 00478 // A NodeRef doesn't know whether it references a leaf node or a branch node. 00479 // It is the responsibility of the caller to use the correct types. 00480 // 00481 // Nodes are never supposed to be empty, and it is invalid to store a node size 00482 // of 0 in a NodeRef. The valid range of sizes is 1-64. 00483 // 00484 //===----------------------------------------------------------------------===// 00485 00486 class NodeRef { 00487 struct CacheAlignedPointerTraits { 00488 static inline void *getAsVoidPointer(void *P) { return P; } 00489 static inline void *getFromVoidPointer(void *P) { return P; } 00490 enum { NumLowBitsAvailable = Log2CacheLine }; 00491 }; 00492 PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip; 00493 00494 public: 00495 /// NodeRef - Create a null ref. 00496 NodeRef() {} 00497 00498 /// operator bool - Detect a null ref. 00499 LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } 00500 00501 /// NodeRef - Create a reference to the node p with n elements. 00502 template <typename NodeT> 00503 NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) { 00504 assert(n <= NodeT::Capacity && "Size too big for node"); 00505 } 00506 00507 /// size - Return the number of elements in the referenced node. 00508 unsigned size() const { return pip.getInt() + 1; } 00509 00510 /// setSize - Update the node size. 00511 void setSize(unsigned n) { pip.setInt(n - 1); } 00512 00513 /// subtree - Access the i'th subtree reference in a branch node. 00514 /// This depends on branch nodes storing the NodeRef array as their first 00515 /// member. 00516 NodeRef &subtree(unsigned i) const { 00517 return reinterpret_cast<NodeRef*>(pip.getPointer())[i]; 00518 } 00519 00520 /// get - Dereference as a NodeT reference. 00521 template <typename NodeT> 00522 NodeT &get() const { 00523 return *reinterpret_cast<NodeT*>(pip.getPointer()); 00524 } 00525 00526 bool operator==(const NodeRef &RHS) const { 00527 if (pip == RHS.pip) 00528 return true; 00529 assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs"); 00530 return false; 00531 } 00532 00533 bool operator!=(const NodeRef &RHS) const { 00534 return !operator==(RHS); 00535 } 00536 }; 00537 00538 //===----------------------------------------------------------------------===// 00539 //--- IntervalMapImpl::LeafNode ---// 00540 //===----------------------------------------------------------------------===// 00541 // 00542 // Leaf nodes store up to N disjoint intervals with corresponding values. 00543 // 00544 // The intervals are kept sorted and fully coalesced so there are no adjacent 00545 // intervals mapping to the same value. 00546 // 00547 // These constraints are always satisfied: 00548 // 00549 // - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals. 00550 // 00551 // - Traits::stopLess(stop(i), start(i + 1) - Sorted. 00552 // 00553 // - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1)) 00554 // - Fully coalesced. 00555 // 00556 //===----------------------------------------------------------------------===// 00557 00558 template <typename KeyT, typename ValT, unsigned N, typename Traits> 00559 class LeafNode : public NodeBase<std::pair<KeyT, KeyT>, ValT, N> { 00560 public: 00561 const KeyT &start(unsigned i) const { return this->first[i].first; } 00562 const KeyT &stop(unsigned i) const { return this->first[i].second; } 00563 const ValT &value(unsigned i) const { return this->second[i]; } 00564 00565 KeyT &start(unsigned i) { return this->first[i].first; } 00566 KeyT &stop(unsigned i) { return this->first[i].second; } 00567 ValT &value(unsigned i) { return this->second[i]; } 00568 00569 /// findFrom - Find the first interval after i that may contain x. 00570 /// @param i Starting index for the search. 00571 /// @param Size Number of elements in node. 00572 /// @param x Key to search for. 00573 /// @return First index with !stopLess(key[i].stop, x), or size. 00574 /// This is the first interval that can possibly contain x. 00575 unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { 00576 assert(i <= Size && Size <= N && "Bad indices"); 00577 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && 00578 "Index is past the needed point"); 00579 while (i != Size && Traits::stopLess(stop(i), x)) ++i; 00580 return i; 00581 } 00582 00583 /// safeFind - Find an interval that is known to exist. This is the same as 00584 /// findFrom except is it assumed that x is at least within range of the last 00585 /// interval. 00586 /// @param i Starting index for the search. 00587 /// @param x Key to search for. 00588 /// @return First index with !stopLess(key[i].stop, x), never size. 00589 /// This is the first interval that can possibly contain x. 00590 unsigned safeFind(unsigned i, KeyT x) const { 00591 assert(i < N && "Bad index"); 00592 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && 00593 "Index is past the needed point"); 00594 while (Traits::stopLess(stop(i), x)) ++i; 00595 assert(i < N && "Unsafe intervals"); 00596 return i; 00597 } 00598 00599 /// safeLookup - Lookup mapped value for a safe key. 00600 /// It is assumed that x is within range of the last entry. 00601 /// @param x Key to search for. 00602 /// @param NotFound Value to return if x is not in any interval. 00603 /// @return The mapped value at x or NotFound. 00604 ValT safeLookup(KeyT x, ValT NotFound) const { 00605 unsigned i = safeFind(0, x); 00606 return Traits::startLess(x, start(i)) ? NotFound : value(i); 00607 } 00608 00609 unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y); 00610 }; 00611 00612 /// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as 00613 /// possible. This may cause the node to grow by 1, or it may cause the node 00614 /// to shrink because of coalescing. 00615 /// @param Pos Starting index = insertFrom(0, size, a) 00616 /// @param Size Number of elements in node. 00617 /// @param a Interval start. 00618 /// @param b Interval stop. 00619 /// @param y Value be mapped. 00620 /// @return (insert position, new size), or (i, Capacity+1) on overflow. 00621 template <typename KeyT, typename ValT, unsigned N, typename Traits> 00622 unsigned LeafNode<KeyT, ValT, N, Traits>:: 00623 insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { 00624 unsigned i = Pos; 00625 assert(i <= Size && Size <= N && "Invalid index"); 00626 assert(!Traits::stopLess(b, a) && "Invalid interval"); 00627 00628 // Verify the findFrom invariant. 00629 assert((i == 0 || Traits::stopLess(stop(i - 1), a))); 00630 assert((i == Size || !Traits::stopLess(stop(i), a))); 00631 assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert"); 00632 00633 // Coalesce with previous interval. 00634 if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) { 00635 Pos = i - 1; 00636 // Also coalesce with next interval? 00637 if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) { 00638 stop(i - 1) = stop(i); 00639 this->erase(i, Size); 00640 return Size - 1; 00641 } 00642 stop(i - 1) = b; 00643 return Size; 00644 } 00645 00646 // Detect overflow. 00647 if (i == N) 00648 return N + 1; 00649 00650 // Add new interval at end. 00651 if (i == Size) { 00652 start(i) = a; 00653 stop(i) = b; 00654 value(i) = y; 00655 return Size + 1; 00656 } 00657 00658 // Try to coalesce with following interval. 00659 if (value(i) == y && Traits::adjacent(b, start(i))) { 00660 start(i) = a; 00661 return Size; 00662 } 00663 00664 // We must insert before i. Detect overflow. 00665 if (Size == N) 00666 return N + 1; 00667 00668 // Insert before i. 00669 this->shift(i, Size); 00670 start(i) = a; 00671 stop(i) = b; 00672 value(i) = y; 00673 return Size + 1; 00674 } 00675 00676 00677 //===----------------------------------------------------------------------===// 00678 //--- IntervalMapImpl::BranchNode ---// 00679 //===----------------------------------------------------------------------===// 00680 // 00681 // A branch node stores references to 1--N subtrees all of the same height. 00682 // 00683 // The key array in a branch node holds the rightmost stop key of each subtree. 00684 // It is redundant to store the last stop key since it can be found in the 00685 // parent node, but doing so makes tree balancing a lot simpler. 00686 // 00687 // It is unusual for a branch node to only have one subtree, but it can happen 00688 // in the root node if it is smaller than the normal nodes. 00689 // 00690 // When all of the leaf nodes from all the subtrees are concatenated, they must 00691 // satisfy the same constraints as a single leaf node. They must be sorted, 00692 // sane, and fully coalesced. 00693 // 00694 //===----------------------------------------------------------------------===// 00695 00696 template <typename KeyT, typename ValT, unsigned N, typename Traits> 00697 class BranchNode : public NodeBase<NodeRef, KeyT, N> { 00698 public: 00699 const KeyT &stop(unsigned i) const { return this->second[i]; } 00700 const NodeRef &subtree(unsigned i) const { return this->first[i]; } 00701 00702 KeyT &stop(unsigned i) { return this->second[i]; } 00703 NodeRef &subtree(unsigned i) { return this->first[i]; } 00704 00705 /// findFrom - Find the first subtree after i that may contain x. 00706 /// @param i Starting index for the search. 00707 /// @param Size Number of elements in node. 00708 /// @param x Key to search for. 00709 /// @return First index with !stopLess(key[i], x), or size. 00710 /// This is the first subtree that can possibly contain x. 00711 unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { 00712 assert(i <= Size && Size <= N && "Bad indices"); 00713 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && 00714 "Index to findFrom is past the needed point"); 00715 while (i != Size && Traits::stopLess(stop(i), x)) ++i; 00716 return i; 00717 } 00718 00719 /// safeFind - Find a subtree that is known to exist. This is the same as 00720 /// findFrom except is it assumed that x is in range. 00721 /// @param i Starting index for the search. 00722 /// @param x Key to search for. 00723 /// @return First index with !stopLess(key[i], x), never size. 00724 /// This is the first subtree that can possibly contain x. 00725 unsigned safeFind(unsigned i, KeyT x) const { 00726 assert(i < N && "Bad index"); 00727 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && 00728 "Index is past the needed point"); 00729 while (Traits::stopLess(stop(i), x)) ++i; 00730 assert(i < N && "Unsafe intervals"); 00731 return i; 00732 } 00733 00734 /// safeLookup - Get the subtree containing x, Assuming that x is in range. 00735 /// @param x Key to search for. 00736 /// @return Subtree containing x 00737 NodeRef safeLookup(KeyT x) const { 00738 return subtree(safeFind(0, x)); 00739 } 00740 00741 /// insert - Insert a new (subtree, stop) pair. 00742 /// @param i Insert position, following entries will be shifted. 00743 /// @param Size Number of elements in node. 00744 /// @param Node Subtree to insert. 00745 /// @param Stop Last key in subtree. 00746 void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) { 00747 assert(Size < N && "branch node overflow"); 00748 assert(i <= Size && "Bad insert position"); 00749 this->shift(i, Size); 00750 subtree(i) = Node; 00751 stop(i) = Stop; 00752 } 00753 }; 00754 00755 //===----------------------------------------------------------------------===// 00756 //--- IntervalMapImpl::Path ---// 00757 //===----------------------------------------------------------------------===// 00758 // 00759 // A Path is used by iterators to represent a position in a B+-tree, and the 00760 // path to get there from the root. 00761 // 00762 // The Path class also contains the tree navigation code that doesn't have to 00763 // be templatized. 00764 // 00765 //===----------------------------------------------------------------------===// 00766 00767 class Path { 00768 /// Entry - Each step in the path is a node pointer and an offset into that 00769 /// node. 00770 struct Entry { 00771 void *node; 00772 unsigned size; 00773 unsigned offset; 00774 00775 Entry(void *Node, unsigned Size, unsigned Offset) 00776 : node(Node), size(Size), offset(Offset) {} 00777 00778 Entry(NodeRef Node, unsigned Offset) 00779 : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {} 00780 00781 NodeRef &subtree(unsigned i) const { 00782 return reinterpret_cast<NodeRef*>(node)[i]; 00783 } 00784 }; 00785 00786 /// path - The path entries, path[0] is the root node, path.back() is a leaf. 00787 SmallVector<Entry, 4> path; 00788 00789 public: 00790 // Node accessors. 00791 template <typename NodeT> NodeT &node(unsigned Level) const { 00792 return *reinterpret_cast<NodeT*>(path[Level].node); 00793 } 00794 unsigned size(unsigned Level) const { return path[Level].size; } 00795 unsigned offset(unsigned Level) const { return path[Level].offset; } 00796 unsigned &offset(unsigned Level) { return path[Level].offset; } 00797 00798 // Leaf accessors. 00799 template <typename NodeT> NodeT &leaf() const { 00800 return *reinterpret_cast<NodeT*>(path.back().node); 00801 } 00802 unsigned leafSize() const { return path.back().size; } 00803 unsigned leafOffset() const { return path.back().offset; } 00804 unsigned &leafOffset() { return path.back().offset; } 00805 00806 /// valid - Return true if path is at a valid node, not at end(). 00807 bool valid() const { 00808 return !path.empty() && path.front().offset < path.front().size; 00809 } 00810 00811 /// height - Return the height of the tree corresponding to this path. 00812 /// This matches map->height in a full path. 00813 unsigned height() const { return path.size() - 1; } 00814 00815 /// subtree - Get the subtree referenced from Level. When the path is 00816 /// consistent, node(Level + 1) == subtree(Level). 00817 /// @param Level 0..height-1. The leaves have no subtrees. 00818 NodeRef &subtree(unsigned Level) const { 00819 return path[Level].subtree(path[Level].offset); 00820 } 00821 00822 /// reset - Reset cached information about node(Level) from subtree(Level -1). 00823 /// @param Level 1..height. THe node to update after parent node changed. 00824 void reset(unsigned Level) { 00825 path[Level] = Entry(subtree(Level - 1), offset(Level)); 00826 } 00827 00828 /// push - Add entry to path. 00829 /// @param Node Node to add, should be subtree(path.size()-1). 00830 /// @param Offset Offset into Node. 00831 void push(NodeRef Node, unsigned Offset) { 00832 path.push_back(Entry(Node, Offset)); 00833 } 00834 00835 /// pop - Remove the last path entry. 00836 void pop() { 00837 path.pop_back(); 00838 } 00839 00840 /// setSize - Set the size of a node both in the path and in the tree. 00841 /// @param Level 0..height. Note that setting the root size won't change 00842 /// map->rootSize. 00843 /// @param Size New node size. 00844 void setSize(unsigned Level, unsigned Size) { 00845 path[Level].size = Size; 00846 if (Level) 00847 subtree(Level - 1).setSize(Size); 00848 } 00849 00850 /// setRoot - Clear the path and set a new root node. 00851 /// @param Node New root node. 00852 /// @param Size New root size. 00853 /// @param Offset Offset into root node. 00854 void setRoot(void *Node, unsigned Size, unsigned Offset) { 00855 path.clear(); 00856 path.push_back(Entry(Node, Size, Offset)); 00857 } 00858 00859 /// replaceRoot - Replace the current root node with two new entries after the 00860 /// tree height has increased. 00861 /// @param Root The new root node. 00862 /// @param Size Number of entries in the new root. 00863 /// @param Offsets Offsets into the root and first branch nodes. 00864 void replaceRoot(void *Root, unsigned Size, IdxPair Offsets); 00865 00866 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. 00867 /// @param Level Get the sibling to node(Level). 00868 /// @return Left sibling, or NodeRef(). 00869 NodeRef getLeftSibling(unsigned Level) const; 00870 00871 /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level 00872 /// unaltered. 00873 /// @param Level Move node(Level). 00874 void moveLeft(unsigned Level); 00875 00876 /// fillLeft - Grow path to Height by taking leftmost branches. 00877 /// @param Height The target height. 00878 void fillLeft(unsigned Height) { 00879 while (height() < Height) 00880 push(subtree(height()), 0); 00881 } 00882 00883 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. 00884 /// @param Level Get the sinbling to node(Level). 00885 /// @return Left sibling, or NodeRef(). 00886 NodeRef getRightSibling(unsigned Level) const; 00887 00888 /// moveRight - Move path to the left sibling at Level. Leave nodes below 00889 /// Level unaltered. 00890 /// @param Level Move node(Level). 00891 void moveRight(unsigned Level); 00892 00893 /// atBegin - Return true if path is at begin(). 00894 bool atBegin() const { 00895 for (unsigned i = 0, e = path.size(); i != e; ++i) 00896 if (path[i].offset != 0) 00897 return false; 00898 return true; 00899 } 00900 00901 /// atLastEntry - Return true if the path is at the last entry of the node at 00902 /// Level. 00903 /// @param Level Node to examine. 00904 bool atLastEntry(unsigned Level) const { 00905 return path[Level].offset == path[Level].size - 1; 00906 } 00907 00908 /// legalizeForInsert - Prepare the path for an insertion at Level. When the 00909 /// path is at end(), node(Level) may not be a legal node. legalizeForInsert 00910 /// ensures that node(Level) is real by moving back to the last node at Level, 00911 /// and setting offset(Level) to size(Level) if required. 00912 /// @param Level The level where an insertion is about to take place. 00913 void legalizeForInsert(unsigned Level) { 00914 if (valid()) 00915 return; 00916 moveLeft(Level); 00917 ++path[Level].offset; 00918 } 00919 }; 00920 00921 } // namespace IntervalMapImpl 00922 00923 00924 //===----------------------------------------------------------------------===// 00925 //--- IntervalMap ----// 00926 //===----------------------------------------------------------------------===// 00927 00928 template <typename KeyT, typename ValT, 00929 unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize, 00930 typename Traits = IntervalMapInfo<KeyT> > 00931 class IntervalMap { 00932 typedef IntervalMapImpl::NodeSizer<KeyT, ValT> Sizer; 00933 typedef IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits> Leaf; 00934 typedef IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits> 00935 Branch; 00936 typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf; 00937 typedef IntervalMapImpl::IdxPair IdxPair; 00938 00939 // The RootLeaf capacity is given as a template parameter. We must compute the 00940 // corresponding RootBranch capacity. 00941 enum { 00942 DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) / 00943 (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)), 00944 RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 00945 }; 00946 00947 typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits> 00948 RootBranch; 00949 00950 // When branched, we store a global start key as well as the branch node. 00951 struct RootBranchData { 00952 KeyT start; 00953 RootBranch node; 00954 }; 00955 00956 enum { 00957 RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ? 00958 sizeof(RootBranchData) : sizeof(RootLeaf) 00959 }; 00960 00961 public: 00962 typedef typename Sizer::Allocator Allocator; 00963 typedef KeyT KeyType; 00964 typedef ValT ValueType; 00965 typedef Traits KeyTraits; 00966 00967 private: 00968 // The root data is either a RootLeaf or a RootBranchData instance. 00969 // We can't put them in a union since C++03 doesn't allow non-trivial 00970 // constructors in unions. 00971 // Instead, we use a char array with pointer alignment. The alignment is 00972 // ensured by the allocator member in the class, but still verified in the 00973 // constructor. We don't support keys or values that are more aligned than a 00974 // pointer. 00975 char data[RootDataSize]; 00976 00977 // Tree height. 00978 // 0: Leaves in root. 00979 // 1: Root points to leaf. 00980 // 2: root->branch->leaf ... 00981 unsigned height; 00982 00983 // Number of entries in the root node. 00984 unsigned rootSize; 00985 00986 // Allocator used for creating external nodes. 00987 Allocator &allocator; 00988 00989 /// dataAs - Represent data as a node type without breaking aliasing rules. 00990 template <typename T> 00991 T &dataAs() const { 00992 union { 00993 const char *d; 00994 T *t; 00995 } u; 00996 u.d = data; 00997 return *u.t; 00998 } 00999 01000 const RootLeaf &rootLeaf() const { 01001 assert(!branched() && "Cannot acces leaf data in branched root"); 01002 return dataAs<RootLeaf>(); 01003 } 01004 RootLeaf &rootLeaf() { 01005 assert(!branched() && "Cannot acces leaf data in branched root"); 01006 return dataAs<RootLeaf>(); 01007 } 01008 RootBranchData &rootBranchData() const { 01009 assert(branched() && "Cannot access branch data in non-branched root"); 01010 return dataAs<RootBranchData>(); 01011 } 01012 RootBranchData &rootBranchData() { 01013 assert(branched() && "Cannot access branch data in non-branched root"); 01014 return dataAs<RootBranchData>(); 01015 } 01016 const RootBranch &rootBranch() const { return rootBranchData().node; } 01017 RootBranch &rootBranch() { return rootBranchData().node; } 01018 KeyT rootBranchStart() const { return rootBranchData().start; } 01019 KeyT &rootBranchStart() { return rootBranchData().start; } 01020 01021 template <typename NodeT> NodeT *newNode() { 01022 return new(allocator.template Allocate<NodeT>()) NodeT(); 01023 } 01024 01025 template <typename NodeT> void deleteNode(NodeT *P) { 01026 P->~NodeT(); 01027 allocator.Deallocate(P); 01028 } 01029 01030 IdxPair branchRoot(unsigned Position); 01031 IdxPair splitRoot(unsigned Position); 01032 01033 void switchRootToBranch() { 01034 rootLeaf().~RootLeaf(); 01035 height = 1; 01036 new (&rootBranchData()) RootBranchData(); 01037 } 01038 01039 void switchRootToLeaf() { 01040 rootBranchData().~RootBranchData(); 01041 height = 0; 01042 new(&rootLeaf()) RootLeaf(); 01043 } 01044 01045 bool branched() const { return height > 0; } 01046 01047 ValT treeSafeLookup(KeyT x, ValT NotFound) const; 01048 void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, 01049 unsigned Level)); 01050 void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); 01051 01052 public: 01053 explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { 01054 assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 && 01055 "Insufficient alignment"); 01056 new(&rootLeaf()) RootLeaf(); 01057 } 01058 01059 ~IntervalMap() { 01060 clear(); 01061 rootLeaf().~RootLeaf(); 01062 } 01063 01064 /// empty - Return true when no intervals are mapped. 01065 bool empty() const { 01066 return rootSize == 0; 01067 } 01068 01069 /// start - Return the smallest mapped key in a non-empty map. 01070 KeyT start() const { 01071 assert(!empty() && "Empty IntervalMap has no start"); 01072 return !branched() ? rootLeaf().start(0) : rootBranchStart(); 01073 } 01074 01075 /// stop - Return the largest mapped key in a non-empty map. 01076 KeyT stop() const { 01077 assert(!empty() && "Empty IntervalMap has no stop"); 01078 return !branched() ? rootLeaf().stop(rootSize - 1) : 01079 rootBranch().stop(rootSize - 1); 01080 } 01081 01082 /// lookup - Return the mapped value at x or NotFound. 01083 ValT lookup(KeyT x, ValT NotFound = ValT()) const { 01084 if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x)) 01085 return NotFound; 01086 return branched() ? treeSafeLookup(x, NotFound) : 01087 rootLeaf().safeLookup(x, NotFound); 01088 } 01089 01090 /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals. 01091 /// It is assumed that no key in the interval is mapped to another value, but 01092 /// overlapping intervals already mapped to y will be coalesced. 01093 void insert(KeyT a, KeyT b, ValT y) { 01094 if (branched() || rootSize == RootLeaf::Capacity) 01095 return find(a).insert(a, b, y); 01096 01097 // Easy insert into root leaf. 01098 unsigned p = rootLeaf().findFrom(0, rootSize, a); 01099 rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y); 01100 } 01101 01102 /// clear - Remove all entries. 01103 void clear(); 01104 01105 class const_iterator; 01106 class iterator; 01107 friend class const_iterator; 01108 friend class iterator; 01109 01110 const_iterator begin() const { 01111 const_iterator I(*this); 01112 I.goToBegin(); 01113 return I; 01114 } 01115 01116 iterator begin() { 01117 iterator I(*this); 01118 I.goToBegin(); 01119 return I; 01120 } 01121 01122 const_iterator end() const { 01123 const_iterator I(*this); 01124 I.goToEnd(); 01125 return I; 01126 } 01127 01128 iterator end() { 01129 iterator I(*this); 01130 I.goToEnd(); 01131 return I; 01132 } 01133 01134 /// find - Return an iterator pointing to the first interval ending at or 01135 /// after x, or end(). 01136 const_iterator find(KeyT x) const { 01137 const_iterator I(*this); 01138 I.find(x); 01139 return I; 01140 } 01141 01142 iterator find(KeyT x) { 01143 iterator I(*this); 01144 I.find(x); 01145 return I; 01146 } 01147 }; 01148 01149 /// treeSafeLookup - Return the mapped value at x or NotFound, assuming a 01150 /// branched root. 01151 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01152 ValT IntervalMap<KeyT, ValT, N, Traits>:: 01153 treeSafeLookup(KeyT x, ValT NotFound) const { 01154 assert(branched() && "treeLookup assumes a branched root"); 01155 01156 IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x); 01157 for (unsigned h = height-1; h; --h) 01158 NR = NR.get<Branch>().safeLookup(x); 01159 return NR.get<Leaf>().safeLookup(x, NotFound); 01160 } 01161 01162 01163 // branchRoot - Switch from a leaf root to a branched root. 01164 // Return the new (root offset, node offset) corresponding to Position. 01165 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01166 IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: 01167 branchRoot(unsigned Position) { 01168 using namespace IntervalMapImpl; 01169 // How many external leaf nodes to hold RootLeaf+1? 01170 const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1; 01171 01172 // Compute element distribution among new nodes. 01173 unsigned size[Nodes]; 01174 IdxPair NewOffset(0, Position); 01175 01176 // Is is very common for the root node to be smaller than external nodes. 01177 if (Nodes == 1) 01178 size[0] = rootSize; 01179 else 01180 NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, size, 01181 Position, true); 01182 01183 // Allocate new nodes. 01184 unsigned pos = 0; 01185 NodeRef node[Nodes]; 01186 for (unsigned n = 0; n != Nodes; ++n) { 01187 Leaf *L = newNode<Leaf>(); 01188 L->copy(rootLeaf(), pos, 0, size[n]); 01189 node[n] = NodeRef(L, size[n]); 01190 pos += size[n]; 01191 } 01192 01193 // Destroy the old leaf node, construct branch node instead. 01194 switchRootToBranch(); 01195 for (unsigned n = 0; n != Nodes; ++n) { 01196 rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1); 01197 rootBranch().subtree(n) = node[n]; 01198 } 01199 rootBranchStart() = node[0].template get<Leaf>().start(0); 01200 rootSize = Nodes; 01201 return NewOffset; 01202 } 01203 01204 // splitRoot - Split the current BranchRoot into multiple Branch nodes. 01205 // Return the new (root offset, node offset) corresponding to Position. 01206 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01207 IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: 01208 splitRoot(unsigned Position) { 01209 using namespace IntervalMapImpl; 01210 // How many external leaf nodes to hold RootBranch+1? 01211 const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1; 01212 01213 // Compute element distribution among new nodes. 01214 unsigned Size[Nodes]; 01215 IdxPair NewOffset(0, Position); 01216 01217 // Is is very common for the root node to be smaller than external nodes. 01218 if (Nodes == 1) 01219 Size[0] = rootSize; 01220 else 01221 NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, Size, 01222 Position, true); 01223 01224 // Allocate new nodes. 01225 unsigned Pos = 0; 01226 NodeRef Node[Nodes]; 01227 for (unsigned n = 0; n != Nodes; ++n) { 01228 Branch *B = newNode<Branch>(); 01229 B->copy(rootBranch(), Pos, 0, Size[n]); 01230 Node[n] = NodeRef(B, Size[n]); 01231 Pos += Size[n]; 01232 } 01233 01234 for (unsigned n = 0; n != Nodes; ++n) { 01235 rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1); 01236 rootBranch().subtree(n) = Node[n]; 01237 } 01238 rootSize = Nodes; 01239 ++height; 01240 return NewOffset; 01241 } 01242 01243 /// visitNodes - Visit each external node. 01244 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01245 void IntervalMap<KeyT, ValT, N, Traits>:: 01246 visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) { 01247 if (!branched()) 01248 return; 01249 SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs; 01250 01251 // Collect level 0 nodes from the root. 01252 for (unsigned i = 0; i != rootSize; ++i) 01253 Refs.push_back(rootBranch().subtree(i)); 01254 01255 // Visit all branch nodes. 01256 for (unsigned h = height - 1; h; --h) { 01257 for (unsigned i = 0, e = Refs.size(); i != e; ++i) { 01258 for (unsigned j = 0, s = Refs[i].size(); j != s; ++j) 01259 NextRefs.push_back(Refs[i].subtree(j)); 01260 (this->*f)(Refs[i], h); 01261 } 01262 Refs.clear(); 01263 Refs.swap(NextRefs); 01264 } 01265 01266 // Visit all leaf nodes. 01267 for (unsigned i = 0, e = Refs.size(); i != e; ++i) 01268 (this->*f)(Refs[i], 0); 01269 } 01270 01271 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01272 void IntervalMap<KeyT, ValT, N, Traits>:: 01273 deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) { 01274 if (Level) 01275 deleteNode(&Node.get<Branch>()); 01276 else 01277 deleteNode(&Node.get<Leaf>()); 01278 } 01279 01280 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01281 void IntervalMap<KeyT, ValT, N, Traits>:: 01282 clear() { 01283 if (branched()) { 01284 visitNodes(&IntervalMap::deleteNode); 01285 switchRootToLeaf(); 01286 } 01287 rootSize = 0; 01288 } 01289 01290 //===----------------------------------------------------------------------===// 01291 //--- IntervalMap::const_iterator ----// 01292 //===----------------------------------------------------------------------===// 01293 01294 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01295 class IntervalMap<KeyT, ValT, N, Traits>::const_iterator : 01296 public std::iterator<std::bidirectional_iterator_tag, ValT> { 01297 protected: 01298 friend class IntervalMap; 01299 01300 // The map referred to. 01301 IntervalMap *map; 01302 01303 // We store a full path from the root to the current position. 01304 // The path may be partially filled, but never between iterator calls. 01305 IntervalMapImpl::Path path; 01306 01307 explicit const_iterator(const IntervalMap &map) : 01308 map(const_cast<IntervalMap*>(&map)) {} 01309 01310 bool branched() const { 01311 assert(map && "Invalid iterator"); 01312 return map->branched(); 01313 } 01314 01315 void setRoot(unsigned Offset) { 01316 if (branched()) 01317 path.setRoot(&map->rootBranch(), map->rootSize, Offset); 01318 else 01319 path.setRoot(&map->rootLeaf(), map->rootSize, Offset); 01320 } 01321 01322 void pathFillFind(KeyT x); 01323 void treeFind(KeyT x); 01324 void treeAdvanceTo(KeyT x); 01325 01326 /// unsafeStart - Writable access to start() for iterator. 01327 KeyT &unsafeStart() const { 01328 assert(valid() && "Cannot access invalid iterator"); 01329 return branched() ? path.leaf<Leaf>().start(path.leafOffset()) : 01330 path.leaf<RootLeaf>().start(path.leafOffset()); 01331 } 01332 01333 /// unsafeStop - Writable access to stop() for iterator. 01334 KeyT &unsafeStop() const { 01335 assert(valid() && "Cannot access invalid iterator"); 01336 return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) : 01337 path.leaf<RootLeaf>().stop(path.leafOffset()); 01338 } 01339 01340 /// unsafeValue - Writable access to value() for iterator. 01341 ValT &unsafeValue() const { 01342 assert(valid() && "Cannot access invalid iterator"); 01343 return branched() ? path.leaf<Leaf>().value(path.leafOffset()) : 01344 path.leaf<RootLeaf>().value(path.leafOffset()); 01345 } 01346 01347 public: 01348 /// const_iterator - Create an iterator that isn't pointing anywhere. 01349 const_iterator() : map(nullptr) {} 01350 01351 /// setMap - Change the map iterated over. This call must be followed by a 01352 /// call to goToBegin(), goToEnd(), or find() 01353 void setMap(const IntervalMap &m) { map = const_cast<IntervalMap*>(&m); } 01354 01355 /// valid - Return true if the current position is valid, false for end(). 01356 bool valid() const { return path.valid(); } 01357 01358 /// atBegin - Return true if the current position is the first map entry. 01359 bool atBegin() const { return path.atBegin(); } 01360 01361 /// start - Return the beginning of the current interval. 01362 const KeyT &start() const { return unsafeStart(); } 01363 01364 /// stop - Return the end of the current interval. 01365 const KeyT &stop() const { return unsafeStop(); } 01366 01367 /// value - Return the mapped value at the current interval. 01368 const ValT &value() const { return unsafeValue(); } 01369 01370 const ValT &operator*() const { return value(); } 01371 01372 bool operator==(const const_iterator &RHS) const { 01373 assert(map == RHS.map && "Cannot compare iterators from different maps"); 01374 if (!valid()) 01375 return !RHS.valid(); 01376 if (path.leafOffset() != RHS.path.leafOffset()) 01377 return false; 01378 return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>(); 01379 } 01380 01381 bool operator!=(const const_iterator &RHS) const { 01382 return !operator==(RHS); 01383 } 01384 01385 /// goToBegin - Move to the first interval in map. 01386 void goToBegin() { 01387 setRoot(0); 01388 if (branched()) 01389 path.fillLeft(map->height); 01390 } 01391 01392 /// goToEnd - Move beyond the last interval in map. 01393 void goToEnd() { 01394 setRoot(map->rootSize); 01395 } 01396 01397 /// preincrement - move to the next interval. 01398 const_iterator &operator++() { 01399 assert(valid() && "Cannot increment end()"); 01400 if (++path.leafOffset() == path.leafSize() && branched()) 01401 path.moveRight(map->height); 01402 return *this; 01403 } 01404 01405 /// postincrement - Dont do that! 01406 const_iterator operator++(int) { 01407 const_iterator tmp = *this; 01408 operator++(); 01409 return tmp; 01410 } 01411 01412 /// predecrement - move to the previous interval. 01413 const_iterator &operator--() { 01414 if (path.leafOffset() && (valid() || !branched())) 01415 --path.leafOffset(); 01416 else 01417 path.moveLeft(map->height); 01418 return *this; 01419 } 01420 01421 /// postdecrement - Dont do that! 01422 const_iterator operator--(int) { 01423 const_iterator tmp = *this; 01424 operator--(); 01425 return tmp; 01426 } 01427 01428 /// find - Move to the first interval with stop >= x, or end(). 01429 /// This is a full search from the root, the current position is ignored. 01430 void find(KeyT x) { 01431 if (branched()) 01432 treeFind(x); 01433 else 01434 setRoot(map->rootLeaf().findFrom(0, map->rootSize, x)); 01435 } 01436 01437 /// advanceTo - Move to the first interval with stop >= x, or end(). 01438 /// The search is started from the current position, and no earlier positions 01439 /// can be found. This is much faster than find() for small moves. 01440 void advanceTo(KeyT x) { 01441 if (!valid()) 01442 return; 01443 if (branched()) 01444 treeAdvanceTo(x); 01445 else 01446 path.leafOffset() = 01447 map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); 01448 } 01449 01450 }; 01451 01452 /// pathFillFind - Complete path by searching for x. 01453 /// @param x Key to search for. 01454 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01455 void IntervalMap<KeyT, ValT, N, Traits>:: 01456 const_iterator::pathFillFind(KeyT x) { 01457 IntervalMapImpl::NodeRef NR = path.subtree(path.height()); 01458 for (unsigned i = map->height - path.height() - 1; i; --i) { 01459 unsigned p = NR.get<Branch>().safeFind(0, x); 01460 path.push(NR, p); 01461 NR = NR.subtree(p); 01462 } 01463 path.push(NR, NR.get<Leaf>().safeFind(0, x)); 01464 } 01465 01466 /// treeFind - Find in a branched tree. 01467 /// @param x Key to search for. 01468 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01469 void IntervalMap<KeyT, ValT, N, Traits>:: 01470 const_iterator::treeFind(KeyT x) { 01471 setRoot(map->rootBranch().findFrom(0, map->rootSize, x)); 01472 if (valid()) 01473 pathFillFind(x); 01474 } 01475 01476 /// treeAdvanceTo - Find position after the current one. 01477 /// @param x Key to search for. 01478 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01479 void IntervalMap<KeyT, ValT, N, Traits>:: 01480 const_iterator::treeAdvanceTo(KeyT x) { 01481 // Can we stay on the same leaf node? 01482 if (!Traits::stopLess(path.leaf<Leaf>().stop(path.leafSize() - 1), x)) { 01483 path.leafOffset() = path.leaf<Leaf>().safeFind(path.leafOffset(), x); 01484 return; 01485 } 01486 01487 // Drop the current leaf. 01488 path.pop(); 01489 01490 // Search towards the root for a usable subtree. 01491 if (path.height()) { 01492 for (unsigned l = path.height() - 1; l; --l) { 01493 if (!Traits::stopLess(path.node<Branch>(l).stop(path.offset(l)), x)) { 01494 // The branch node at l+1 is usable 01495 path.offset(l + 1) = 01496 path.node<Branch>(l + 1).safeFind(path.offset(l + 1), x); 01497 return pathFillFind(x); 01498 } 01499 path.pop(); 01500 } 01501 // Is the level-1 Branch usable? 01502 if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) { 01503 path.offset(1) = path.node<Branch>(1).safeFind(path.offset(1), x); 01504 return pathFillFind(x); 01505 } 01506 } 01507 01508 // We reached the root. 01509 setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x)); 01510 if (valid()) 01511 pathFillFind(x); 01512 } 01513 01514 //===----------------------------------------------------------------------===// 01515 //--- IntervalMap::iterator ----// 01516 //===----------------------------------------------------------------------===// 01517 01518 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01519 class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator { 01520 friend class IntervalMap; 01521 typedef IntervalMapImpl::IdxPair IdxPair; 01522 01523 explicit iterator(IntervalMap &map) : const_iterator(map) {} 01524 01525 void setNodeStop(unsigned Level, KeyT Stop); 01526 bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop); 01527 template <typename NodeT> bool overflow(unsigned Level); 01528 void treeInsert(KeyT a, KeyT b, ValT y); 01529 void eraseNode(unsigned Level); 01530 void treeErase(bool UpdateRoot = true); 01531 bool canCoalesceLeft(KeyT Start, ValT x); 01532 bool canCoalesceRight(KeyT Stop, ValT x); 01533 01534 public: 01535 /// iterator - Create null iterator. 01536 iterator() {} 01537 01538 /// setStart - Move the start of the current interval. 01539 /// This may cause coalescing with the previous interval. 01540 /// @param a New start key, must not overlap the previous interval. 01541 void setStart(KeyT a); 01542 01543 /// setStop - Move the end of the current interval. 01544 /// This may cause coalescing with the following interval. 01545 /// @param b New stop key, must not overlap the following interval. 01546 void setStop(KeyT b); 01547 01548 /// setValue - Change the mapped value of the current interval. 01549 /// This may cause coalescing with the previous and following intervals. 01550 /// @param x New value. 01551 void setValue(ValT x); 01552 01553 /// setStartUnchecked - Move the start of the current interval without 01554 /// checking for coalescing or overlaps. 01555 /// This should only be used when it is known that coalescing is not required. 01556 /// @param a New start key. 01557 void setStartUnchecked(KeyT a) { this->unsafeStart() = a; } 01558 01559 /// setStopUnchecked - Move the end of the current interval without checking 01560 /// for coalescing or overlaps. 01561 /// This should only be used when it is known that coalescing is not required. 01562 /// @param b New stop key. 01563 void setStopUnchecked(KeyT b) { 01564 this->unsafeStop() = b; 01565 // Update keys in branch nodes as well. 01566 if (this->path.atLastEntry(this->path.height())) 01567 setNodeStop(this->path.height(), b); 01568 } 01569 01570 /// setValueUnchecked - Change the mapped value of the current interval 01571 /// without checking for coalescing. 01572 /// @param x New value. 01573 void setValueUnchecked(ValT x) { this->unsafeValue() = x; } 01574 01575 /// insert - Insert mapping [a;b] -> y before the current position. 01576 void insert(KeyT a, KeyT b, ValT y); 01577 01578 /// erase - Erase the current interval. 01579 void erase(); 01580 01581 iterator &operator++() { 01582 const_iterator::operator++(); 01583 return *this; 01584 } 01585 01586 iterator operator++(int) { 01587 iterator tmp = *this; 01588 operator++(); 01589 return tmp; 01590 } 01591 01592 iterator &operator--() { 01593 const_iterator::operator--(); 01594 return *this; 01595 } 01596 01597 iterator operator--(int) { 01598 iterator tmp = *this; 01599 operator--(); 01600 return tmp; 01601 } 01602 01603 }; 01604 01605 /// canCoalesceLeft - Can the current interval coalesce to the left after 01606 /// changing start or value? 01607 /// @param Start New start of current interval. 01608 /// @param Value New value for current interval. 01609 /// @return True when updating the current interval would enable coalescing. 01610 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01611 bool IntervalMap<KeyT, ValT, N, Traits>:: 01612 iterator::canCoalesceLeft(KeyT Start, ValT Value) { 01613 using namespace IntervalMapImpl; 01614 Path &P = this->path; 01615 if (!this->branched()) { 01616 unsigned i = P.leafOffset(); 01617 RootLeaf &Node = P.leaf<RootLeaf>(); 01618 return i && Node.value(i-1) == Value && 01619 Traits::adjacent(Node.stop(i-1), Start); 01620 } 01621 // Branched. 01622 if (unsigned i = P.leafOffset()) { 01623 Leaf &Node = P.leaf<Leaf>(); 01624 return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start); 01625 } else if (NodeRef NR = P.getLeftSibling(P.height())) { 01626 unsigned i = NR.size() - 1; 01627 Leaf &Node = NR.get<Leaf>(); 01628 return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start); 01629 } 01630 return false; 01631 } 01632 01633 /// canCoalesceRight - Can the current interval coalesce to the right after 01634 /// changing stop or value? 01635 /// @param Stop New stop of current interval. 01636 /// @param Value New value for current interval. 01637 /// @return True when updating the current interval would enable coalescing. 01638 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01639 bool IntervalMap<KeyT, ValT, N, Traits>:: 01640 iterator::canCoalesceRight(KeyT Stop, ValT Value) { 01641 using namespace IntervalMapImpl; 01642 Path &P = this->path; 01643 unsigned i = P.leafOffset() + 1; 01644 if (!this->branched()) { 01645 if (i >= P.leafSize()) 01646 return false; 01647 RootLeaf &Node = P.leaf<RootLeaf>(); 01648 return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); 01649 } 01650 // Branched. 01651 if (i < P.leafSize()) { 01652 Leaf &Node = P.leaf<Leaf>(); 01653 return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); 01654 } else if (NodeRef NR = P.getRightSibling(P.height())) { 01655 Leaf &Node = NR.get<Leaf>(); 01656 return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0)); 01657 } 01658 return false; 01659 } 01660 01661 /// setNodeStop - Update the stop key of the current node at level and above. 01662 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01663 void IntervalMap<KeyT, ValT, N, Traits>:: 01664 iterator::setNodeStop(unsigned Level, KeyT Stop) { 01665 // There are no references to the root node, so nothing to update. 01666 if (!Level) 01667 return; 01668 IntervalMapImpl::Path &P = this->path; 01669 // Update nodes pointing to the current node. 01670 while (--Level) { 01671 P.node<Branch>(Level).stop(P.offset(Level)) = Stop; 01672 if (!P.atLastEntry(Level)) 01673 return; 01674 } 01675 // Update root separately since it has a different layout. 01676 P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop; 01677 } 01678 01679 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01680 void IntervalMap<KeyT, ValT, N, Traits>:: 01681 iterator::setStart(KeyT a) { 01682 assert(Traits::stopLess(a, this->stop()) && "Cannot move start beyond stop"); 01683 KeyT &CurStart = this->unsafeStart(); 01684 if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { 01685 CurStart = a; 01686 return; 01687 } 01688 // Coalesce with the interval to the left. 01689 --*this; 01690 a = this->start(); 01691 erase(); 01692 setStartUnchecked(a); 01693 } 01694 01695 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01696 void IntervalMap<KeyT, ValT, N, Traits>:: 01697 iterator::setStop(KeyT b) { 01698 assert(Traits::stopLess(this->start(), b) && "Cannot move stop beyond start"); 01699 if (Traits::startLess(b, this->stop()) || 01700 !canCoalesceRight(b, this->value())) { 01701 setStopUnchecked(b); 01702 return; 01703 } 01704 // Coalesce with interval to the right. 01705 KeyT a = this->start(); 01706 erase(); 01707 setStartUnchecked(a); 01708 } 01709 01710 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01711 void IntervalMap<KeyT, ValT, N, Traits>:: 01712 iterator::setValue(ValT x) { 01713 setValueUnchecked(x); 01714 if (canCoalesceRight(this->stop(), x)) { 01715 KeyT a = this->start(); 01716 erase(); 01717 setStartUnchecked(a); 01718 } 01719 if (canCoalesceLeft(this->start(), x)) { 01720 --*this; 01721 KeyT a = this->start(); 01722 erase(); 01723 setStartUnchecked(a); 01724 } 01725 } 01726 01727 /// insertNode - insert a node before the current path at level. 01728 /// Leave the current path pointing at the new node. 01729 /// @param Level path index of the node to be inserted. 01730 /// @param Node The node to be inserted. 01731 /// @param Stop The last index in the new node. 01732 /// @return True if the tree height was increased. 01733 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01734 bool IntervalMap<KeyT, ValT, N, Traits>:: 01735 iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { 01736 assert(Level && "Cannot insert next to the root"); 01737 bool SplitRoot = false; 01738 IntervalMap &IM = *this->map; 01739 IntervalMapImpl::Path &P = this->path; 01740 01741 if (Level == 1) { 01742 // Insert into the root branch node. 01743 if (IM.rootSize < RootBranch::Capacity) { 01744 IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); 01745 P.setSize(0, ++IM.rootSize); 01746 P.reset(Level); 01747 return SplitRoot; 01748 } 01749 01750 // We need to split the root while keeping our position. 01751 SplitRoot = true; 01752 IdxPair Offset = IM.splitRoot(P.offset(0)); 01753 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); 01754 01755 // Fall through to insert at the new higher level. 01756 ++Level; 01757 } 01758 01759 // When inserting before end(), make sure we have a valid path. 01760 P.legalizeForInsert(--Level); 01761 01762 // Insert into the branch node at Level-1. 01763 if (P.size(Level) == Branch::Capacity) { 01764 // Branch node is full, handle handle the overflow. 01765 assert(!SplitRoot && "Cannot overflow after splitting the root"); 01766 SplitRoot = overflow<Branch>(Level); 01767 Level += SplitRoot; 01768 } 01769 P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop); 01770 P.setSize(Level, P.size(Level) + 1); 01771 if (P.atLastEntry(Level)) 01772 setNodeStop(Level, Stop); 01773 P.reset(Level + 1); 01774 return SplitRoot; 01775 } 01776 01777 // insert 01778 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01779 void IntervalMap<KeyT, ValT, N, Traits>:: 01780 iterator::insert(KeyT a, KeyT b, ValT y) { 01781 if (this->branched()) 01782 return treeInsert(a, b, y); 01783 IntervalMap &IM = *this->map; 01784 IntervalMapImpl::Path &P = this->path; 01785 01786 // Try simple root leaf insert. 01787 unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y); 01788 01789 // Was the root node insert successful? 01790 if (Size <= RootLeaf::Capacity) { 01791 P.setSize(0, IM.rootSize = Size); 01792 return; 01793 } 01794 01795 // Root leaf node is full, we must branch. 01796 IdxPair Offset = IM.branchRoot(P.leafOffset()); 01797 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); 01798 01799 // Now it fits in the new leaf. 01800 treeInsert(a, b, y); 01801 } 01802 01803 01804 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01805 void IntervalMap<KeyT, ValT, N, Traits>:: 01806 iterator::treeInsert(KeyT a, KeyT b, ValT y) { 01807 using namespace IntervalMapImpl; 01808 Path &P = this->path; 01809 01810 if (!P.valid()) 01811 P.legalizeForInsert(this->map->height); 01812 01813 // Check if this insertion will extend the node to the left. 01814 if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf<Leaf>().start(0))) { 01815 // Node is growing to the left, will it affect a left sibling node? 01816 if (NodeRef Sib = P.getLeftSibling(P.height())) { 01817 Leaf &SibLeaf = Sib.get<Leaf>(); 01818 unsigned SibOfs = Sib.size() - 1; 01819 if (SibLeaf.value(SibOfs) == y && 01820 Traits::adjacent(SibLeaf.stop(SibOfs), a)) { 01821 // This insertion will coalesce with the last entry in SibLeaf. We can 01822 // handle it in two ways: 01823 // 1. Extend SibLeaf.stop to b and be done, or 01824 // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue. 01825 // We prefer 1., but need 2 when coalescing to the right as well. 01826 Leaf &CurLeaf = P.leaf<Leaf>(); 01827 P.moveLeft(P.height()); 01828 if (Traits::stopLess(b, CurLeaf.start(0)) && 01829 (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) { 01830 // Easy, just extend SibLeaf and we're done. 01831 setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b); 01832 return; 01833 } else { 01834 // We have both left and right coalescing. Erase the old SibLeaf entry 01835 // and continue inserting the larger interval. 01836 a = SibLeaf.start(SibOfs); 01837 treeErase(/* UpdateRoot= */false); 01838 } 01839 } 01840 } else { 01841 // No left sibling means we are at begin(). Update cached bound. 01842 this->map->rootBranchStart() = a; 01843 } 01844 } 01845 01846 // When we are inserting at the end of a leaf node, we must update stops. 01847 unsigned Size = P.leafSize(); 01848 bool Grow = P.leafOffset() == Size; 01849 Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), Size, a, b, y); 01850 01851 // Leaf insertion unsuccessful? Overflow and try again. 01852 if (Size > Leaf::Capacity) { 01853 overflow<Leaf>(P.height()); 01854 Grow = P.leafOffset() == P.leafSize(); 01855 Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y); 01856 assert(Size <= Leaf::Capacity && "overflow() didn't make room"); 01857 } 01858 01859 // Inserted, update offset and leaf size. 01860 P.setSize(P.height(), Size); 01861 01862 // Insert was the last node entry, update stops. 01863 if (Grow) 01864 setNodeStop(P.height(), b); 01865 } 01866 01867 /// erase - erase the current interval and move to the next position. 01868 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01869 void IntervalMap<KeyT, ValT, N, Traits>:: 01870 iterator::erase() { 01871 IntervalMap &IM = *this->map; 01872 IntervalMapImpl::Path &P = this->path; 01873 assert(P.valid() && "Cannot erase end()"); 01874 if (this->branched()) 01875 return treeErase(); 01876 IM.rootLeaf().erase(P.leafOffset(), IM.rootSize); 01877 P.setSize(0, --IM.rootSize); 01878 } 01879 01880 /// treeErase - erase() for a branched tree. 01881 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01882 void IntervalMap<KeyT, ValT, N, Traits>:: 01883 iterator::treeErase(bool UpdateRoot) { 01884 IntervalMap &IM = *this->map; 01885 IntervalMapImpl::Path &P = this->path; 01886 Leaf &Node = P.leaf<Leaf>(); 01887 01888 // Nodes are not allowed to become empty. 01889 if (P.leafSize() == 1) { 01890 IM.deleteNode(&Node); 01891 eraseNode(IM.height); 01892 // Update rootBranchStart if we erased begin(). 01893 if (UpdateRoot && IM.branched() && P.valid() && P.atBegin()) 01894 IM.rootBranchStart() = P.leaf<Leaf>().start(0); 01895 return; 01896 } 01897 01898 // Erase current entry. 01899 Node.erase(P.leafOffset(), P.leafSize()); 01900 unsigned NewSize = P.leafSize() - 1; 01901 P.setSize(IM.height, NewSize); 01902 // When we erase the last entry, update stop and move to a legal position. 01903 if (P.leafOffset() == NewSize) { 01904 setNodeStop(IM.height, Node.stop(NewSize - 1)); 01905 P.moveRight(IM.height); 01906 } else if (UpdateRoot && P.atBegin()) 01907 IM.rootBranchStart() = P.leaf<Leaf>().start(0); 01908 } 01909 01910 /// eraseNode - Erase the current node at Level from its parent and move path to 01911 /// the first entry of the next sibling node. 01912 /// The node must be deallocated by the caller. 01913 /// @param Level 1..height, the root node cannot be erased. 01914 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01915 void IntervalMap<KeyT, ValT, N, Traits>:: 01916 iterator::eraseNode(unsigned Level) { 01917 assert(Level && "Cannot erase root node"); 01918 IntervalMap &IM = *this->map; 01919 IntervalMapImpl::Path &P = this->path; 01920 01921 if (--Level == 0) { 01922 IM.rootBranch().erase(P.offset(0), IM.rootSize); 01923 P.setSize(0, --IM.rootSize); 01924 // If this cleared the root, switch to height=0. 01925 if (IM.empty()) { 01926 IM.switchRootToLeaf(); 01927 this->setRoot(0); 01928 return; 01929 } 01930 } else { 01931 // Remove node ref from branch node at Level. 01932 Branch &Parent = P.node<Branch>(Level); 01933 if (P.size(Level) == 1) { 01934 // Branch node became empty, remove it recursively. 01935 IM.deleteNode(&Parent); 01936 eraseNode(Level); 01937 } else { 01938 // Branch node won't become empty. 01939 Parent.erase(P.offset(Level), P.size(Level)); 01940 unsigned NewSize = P.size(Level) - 1; 01941 P.setSize(Level, NewSize); 01942 // If we removed the last branch, update stop and move to a legal pos. 01943 if (P.offset(Level) == NewSize) { 01944 setNodeStop(Level, Parent.stop(NewSize - 1)); 01945 P.moveRight(Level); 01946 } 01947 } 01948 } 01949 // Update path cache for the new right sibling position. 01950 if (P.valid()) { 01951 P.reset(Level + 1); 01952 P.offset(Level + 1) = 0; 01953 } 01954 } 01955 01956 /// overflow - Distribute entries of the current node evenly among 01957 /// its siblings and ensure that the current node is not full. 01958 /// This may require allocating a new node. 01959 /// @tparam NodeT The type of node at Level (Leaf or Branch). 01960 /// @param Level path index of the overflowing node. 01961 /// @return True when the tree height was changed. 01962 template <typename KeyT, typename ValT, unsigned N, typename Traits> 01963 template <typename NodeT> 01964 bool IntervalMap<KeyT, ValT, N, Traits>:: 01965 iterator::overflow(unsigned Level) { 01966 using namespace IntervalMapImpl; 01967 Path &P = this->path; 01968 unsigned CurSize[4]; 01969 NodeT *Node[4]; 01970 unsigned Nodes = 0; 01971 unsigned Elements = 0; 01972 unsigned Offset = P.offset(Level); 01973 01974 // Do we have a left sibling? 01975 NodeRef LeftSib = P.getLeftSibling(Level); 01976 if (LeftSib) { 01977 Offset += Elements = CurSize[Nodes] = LeftSib.size(); 01978 Node[Nodes++] = &LeftSib.get<NodeT>(); 01979 } 01980 01981 // Current node. 01982 Elements += CurSize[Nodes] = P.size(Level); 01983 Node[Nodes++] = &P.node<NodeT>(Level); 01984 01985 // Do we have a right sibling? 01986 NodeRef RightSib = P.getRightSibling(Level); 01987 if (RightSib) { 01988 Elements += CurSize[Nodes] = RightSib.size(); 01989 Node[Nodes++] = &RightSib.get<NodeT>(); 01990 } 01991 01992 // Do we need to allocate a new node? 01993 unsigned NewNode = 0; 01994 if (Elements + 1 > Nodes * NodeT::Capacity) { 01995 // Insert NewNode at the penultimate position, or after a single node. 01996 NewNode = Nodes == 1 ? 1 : Nodes - 1; 01997 CurSize[Nodes] = CurSize[NewNode]; 01998 Node[Nodes] = Node[NewNode]; 01999 CurSize[NewNode] = 0; 02000 Node[NewNode] = this->map->template newNode<NodeT>(); 02001 ++Nodes; 02002 } 02003 02004 // Compute the new element distribution. 02005 unsigned NewSize[4]; 02006 IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity, 02007 CurSize, NewSize, Offset, true); 02008 adjustSiblingSizes(Node, Nodes, CurSize, NewSize); 02009 02010 // Move current location to the leftmost node. 02011 if (LeftSib) 02012 P.moveLeft(Level); 02013 02014 // Elements have been rearranged, now update node sizes and stops. 02015 bool SplitRoot = false; 02016 unsigned Pos = 0; 02017 for (;;) { 02018 KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); 02019 if (NewNode && Pos == NewNode) { 02020 SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); 02021 Level += SplitRoot; 02022 } else { 02023 P.setSize(Level, NewSize[Pos]); 02024 setNodeStop(Level, Stop); 02025 } 02026 if (Pos + 1 == Nodes) 02027 break; 02028 P.moveRight(Level); 02029 ++Pos; 02030 } 02031 02032 // Where was I? Find NewOffset. 02033 while(Pos != NewOffset.first) { 02034 P.moveLeft(Level); 02035 --Pos; 02036 } 02037 P.offset(Level) = NewOffset.second; 02038 return SplitRoot; 02039 } 02040 02041 //===----------------------------------------------------------------------===// 02042 //--- IntervalMapOverlaps ----// 02043 //===----------------------------------------------------------------------===// 02044 02045 /// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two 02046 /// IntervalMaps. The maps may be different, but the KeyT and Traits types 02047 /// should be the same. 02048 /// 02049 /// Typical uses: 02050 /// 02051 /// 1. Test for overlap: 02052 /// bool overlap = IntervalMapOverlaps(a, b).valid(); 02053 /// 02054 /// 2. Enumerate overlaps: 02055 /// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... } 02056 /// 02057 template <typename MapA, typename MapB> 02058 class IntervalMapOverlaps { 02059 typedef typename MapA::KeyType KeyType; 02060 typedef typename MapA::KeyTraits Traits; 02061 typename MapA::const_iterator posA; 02062 typename MapB::const_iterator posB; 02063 02064 /// advance - Move posA and posB forward until reaching an overlap, or until 02065 /// either meets end. 02066 /// Don't move the iterators if they are already overlapping. 02067 void advance() { 02068 if (!valid()) 02069 return; 02070 02071 if (Traits::stopLess(posA.stop(), posB.start())) { 02072 // A ends before B begins. Catch up. 02073 posA.advanceTo(posB.start()); 02074 if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) 02075 return; 02076 } else if (Traits::stopLess(posB.stop(), posA.start())) { 02077 // B ends before A begins. Catch up. 02078 posB.advanceTo(posA.start()); 02079 if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) 02080 return; 02081 } else 02082 // Already overlapping. 02083 return; 02084 02085 for (;;) { 02086 // Make a.end > b.start. 02087 posA.advanceTo(posB.start()); 02088 if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) 02089 return; 02090 // Make b.end > a.start. 02091 posB.advanceTo(posA.start()); 02092 if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) 02093 return; 02094 } 02095 } 02096 02097 public: 02098 /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b. 02099 IntervalMapOverlaps(const MapA &a, const MapB &b) 02100 : posA(b.empty() ? a.end() : a.find(b.start())), 02101 posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); } 02102 02103 /// valid - Return true if iterator is at an overlap. 02104 bool valid() const { 02105 return posA.valid() && posB.valid(); 02106 } 02107 02108 /// a - access the left hand side in the overlap. 02109 const typename MapA::const_iterator &a() const { return posA; } 02110 02111 /// b - access the right hand side in the overlap. 02112 const typename MapB::const_iterator &b() const { return posB; } 02113 02114 /// start - Beginning of the overlapping interval. 02115 KeyType start() const { 02116 KeyType ak = a().start(); 02117 KeyType bk = b().start(); 02118 return Traits::startLess(ak, bk) ? bk : ak; 02119 } 02120 02121 /// stop - End of the overlapping interval. 02122 KeyType stop() const { 02123 KeyType ak = a().stop(); 02124 KeyType bk = b().stop(); 02125 return Traits::startLess(ak, bk) ? ak : bk; 02126 } 02127 02128 /// skipA - Move to the next overlap that doesn't involve a(). 02129 void skipA() { 02130 ++posA; 02131 advance(); 02132 } 02133 02134 /// skipB - Move to the next overlap that doesn't involve b(). 02135 void skipB() { 02136 ++posB; 02137 advance(); 02138 } 02139 02140 /// Preincrement - Move to the next overlap. 02141 IntervalMapOverlaps &operator++() { 02142 // Bump the iterator that ends first. The other one may have more overlaps. 02143 if (Traits::startLess(posB.stop(), posA.stop())) 02144 skipB(); 02145 else 02146 skipA(); 02147 return *this; 02148 } 02149 02150 /// advanceTo - Move to the first overlapping interval with 02151 /// stopLess(x, stop()). 02152 void advanceTo(KeyType x) { 02153 if (!valid()) 02154 return; 02155 // Make sure advanceTo sees monotonic keys. 02156 if (Traits::stopLess(posA.stop(), x)) 02157 posA.advanceTo(x); 02158 if (Traits::stopLess(posB.stop(), x)) 02159 posB.advanceTo(x); 02160 advance(); 02161 } 02162 }; 02163 02164 } // namespace llvm 02165 02166 #endif