IntervalTree.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- IntervalTree.h ------------------------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file implements an interval tree.
  15. //
  16. // Further information:
  17. // https://en.wikipedia.org/wiki/Interval_tree
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #ifndef LLVM_ADT_INTERVALTREE_H
  21. #define LLVM_ADT_INTERVALTREE_H
  22. #include "llvm/ADT/SmallSet.h"
  23. #include "llvm/ADT/SmallVector.h"
  24. #include "llvm/Support/Allocator.h"
  25. #include "llvm/Support/Format.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. #include <algorithm>
  28. #include <cassert>
  29. #include <iterator>
  30. // IntervalTree is a light tree data structure to hold intervals. It allows
  31. // finding all intervals that overlap with any given point. At this time,
  32. // it does not support any deletion or rebalancing operations.
  33. //
  34. // The IntervalTree is designed to be set up once, and then queried without
  35. // any further additions.
  36. //
  37. // Synopsis:
  38. // Closed intervals delimited by PointT objects are mapped to ValueT objects.
  39. //
  40. // Restrictions:
  41. // PointT must be a fundamental type.
  42. // ValueT must be a fundamental or pointer type.
  43. //
  44. // template <typename PointT, typename ValueT, typename DataT>
  45. // class IntervalTree {
  46. // public:
  47. //
  48. // IntervalTree();
  49. // ~IntervalTree():
  50. //
  51. // using IntervalReferences = SmallVector<IntervalData *>;
  52. //
  53. // void create();
  54. // void insert(PointT Left, PointT Right, ValueT Value);
  55. //
  56. // IntervalReferences getContaining(PointT Point);
  57. // static void sortIntervals(IntervalReferences &Intervals, Sorting Sort);
  58. //
  59. // find_iterator begin(PointType Point) const;
  60. // find_iterator end() const;
  61. //
  62. // bool empty() const;
  63. // void clear();
  64. //
  65. // void print(raw_ostream &OS, bool HexFormat = true);
  66. // };
  67. //
  68. //===----------------------------------------------------------------------===//
  69. //
  70. // In the below given dataset
  71. //
  72. // [a, b] <- (x)
  73. //
  74. // 'a' and 'b' describe a range and 'x' the value for that interval.
  75. //
  76. // The following data are purely for illustrative purposes:
  77. //
  78. // [30, 35] <- (3035), [39, 50] <- (3950), [55, 61] <- (5561),
  79. // [31, 56] <- (3156), [12, 21] <- (1221), [25, 41] <- (2541),
  80. // [49, 65] <- (4965), [71, 79] <- (7179), [11, 16] <- (1116),
  81. // [20, 30] <- (2030), [36, 54] <- (3654), [60, 70] <- (6070),
  82. // [74, 80] <- (7480), [15, 40] <- (1540), [43, 43] <- (4343),
  83. // [50, 75] <- (5075), [10, 85] <- (1085)
  84. //
  85. // The data represents a set of overlapping intervals:
  86. //
  87. // 30--35 39------------50 55----61
  88. // 31------------------------56
  89. // 12--------21 25------------41 49-------------65 71-----79
  90. // 11----16 20-----30 36----------------54 60------70 74---- 80
  91. // 15---------------------40 43--43 50--------------------75
  92. // 10----------------------------------------------------------------------85
  93. //
  94. // The items are stored in a binary tree with each node storing:
  95. //
  96. // MP: A middle point.
  97. // IL: All intervals whose left value are completely to the left of the middle
  98. // point. They are sorted in ascending order by their beginning point.
  99. // IR: All intervals whose right value are completely to the right of the
  100. // middle point. They are sorted in descending order by their ending point.
  101. // LS: Left subtree.
  102. // RS: Right subtree.
  103. //
  104. // As IL and IR will contain the same intervals, in order to optimize space,
  105. // instead of storing intervals on each node, we use two vectors that will
  106. // contain the intervals described by IL and IR. Each node will contain an
  107. // index into that vector (global bucket), to indicate the beginning of the
  108. // intervals assigned to the node.
  109. //
  110. // The following is the output from print():
  111. //
  112. // 0: MP:43 IR [10,85] [31,56] [36,54] [39,50] [43,43]
  113. // 0: MP:43 IL [10,85] [31,56] [36,54] [39,50] [43,43]
  114. // 1: MP:25 IR [25,41] [15,40] [20,30]
  115. // 1: MP:25 IL [15,40] [20,30] [25,41]
  116. // 2: MP:15 IR [12,21] [11,16]
  117. // 2: MP:15 IL [11,16] [12,21]
  118. // 2: MP:36 IR []
  119. // 2: MP:36 IL []
  120. // 3: MP:31 IR [30,35]
  121. // 3: MP:31 IL [30,35]
  122. // 1: MP:61 IR [50,75] [60,70] [49,65] [55,61]
  123. // 1: MP:61 IL [49,65] [50,75] [55,61] [60,70]
  124. // 2: MP:74 IR [74,80] [71,79]
  125. // 2: MP:74 IL [71,79] [74,80]
  126. //
  127. // with:
  128. // 0: Root Node.
  129. // MP: Middle point.
  130. // IL: Intervals to the left (in ascending order by beginning point).
  131. // IR: Intervals to the right (in descending order by ending point).
  132. //
  133. // Root
  134. // |
  135. // V
  136. // +------------MP:43------------+
  137. // | IL IR |
  138. // | [10,85] [10,85] |
  139. // LS | [31,56] [31,56] | RS
  140. // | [36,54] [36,54] |
  141. // | [39,50] [39,50] |
  142. // | [43,43] [43,43] |
  143. // V V
  144. // +------------MP:25------------+ MP:61------------+
  145. // | IL IR | IL IR |
  146. // | [15,40] [25,41] | [49,65] [50,75] |
  147. // LS | [20,30] [15,40] | RS [50,75] [60,70] | RS
  148. // | [25,41] [20,30] | [55,61] [49,65] |
  149. // | | [60,70] [55,61] |
  150. // V V V
  151. // MP:15 +-------MP:36 MP:74
  152. // IL IR | IL IR IL IR
  153. // [11,16] [12,21] LS | [] [] [71,79] [74,80]
  154. // [12,21] [11,16] | [74,80] [71,79]
  155. // V
  156. // MP:31
  157. // IL IR
  158. // [30,35] [30,35]
  159. //
  160. // The creation of an interval tree is done in 2 steps:
  161. // 1) Insert the interval items by calling
  162. // void insert(PointT Left, PointT Right, ValueT Value);
  163. // Left, Right: the interval left and right limits.
  164. // Value: the data associated with that specific interval.
  165. //
  166. // 2) Create the interval tree by calling
  167. // void create();
  168. //
  169. // Once the tree is created, it is switched to query mode.
  170. // Query the tree by using iterators or container.
  171. //
  172. // a) Iterators over intervals overlapping the given point with very weak
  173. // ordering guarantees.
  174. // find_iterator begin(PointType Point) const;
  175. // find_iterator end() const;
  176. // Point: a target point to be tested for inclusion in any interval.
  177. //
  178. // b) Container:
  179. // IntervalReferences getContaining(PointT Point);
  180. // Point: a target point to be tested for inclusion in any interval.
  181. // Returns vector with all the intervals containing the target point.
  182. //
  183. // The returned intervals are in their natural tree location. They can
  184. // be sorted:
  185. //
  186. // static void sortIntervals(IntervalReferences &Intervals, Sorting Sort);
  187. //
  188. // Ability to print the constructed interval tree:
  189. // void print(raw_ostream &OS, bool HexFormat = true);
  190. // Display the associated data in hexadecimal format.
  191. namespace llvm {
  192. //===----------------------------------------------------------------------===//
  193. //--- IntervalData ----//
  194. //===----------------------------------------------------------------------===//
  195. /// An interval data composed by a \a Left and \a Right points and an
  196. /// associated \a Value.
  197. /// \a PointT corresponds to the interval endpoints type.
  198. /// \a ValueT corresponds to the interval value type.
  199. template <typename PointT, typename ValueT> class IntervalData {
  200. protected:
  201. using PointType = PointT;
  202. using ValueType = ValueT;
  203. private:
  204. PointType Left;
  205. PointType Right;
  206. ValueType Value;
  207. public:
  208. IntervalData() = delete;
  209. IntervalData(PointType Left, PointType Right, ValueType Value)
  210. : Left(Left), Right(Right), Value(Value) {
  211. assert(Left <= Right && "'Left' must be less or equal to 'Right'");
  212. }
  213. virtual ~IntervalData() = default;
  214. PointType left() const { return Left; }
  215. PointType right() const { return Right; }
  216. ValueType value() const { return Value; }
  217. /// Return true if \a Point is inside the left bound of closed interval \a
  218. /// [Left;Right]. This is Left <= Point for closed intervals.
  219. bool left(const PointType &Point) const { return left() <= Point; }
  220. /// Return true if \a Point is inside the right bound of closed interval \a
  221. /// [Left;Right]. This is Point <= Right for closed intervals.
  222. bool right(const PointType &Point) const { return Point <= right(); }
  223. /// Return true when \a Point is contained in interval \a [Left;Right].
  224. /// This is Left <= Point <= Right for closed intervals.
  225. bool contains(const PointType &Point) const {
  226. return left(Point) && right(Point);
  227. }
  228. };
  229. //===----------------------------------------------------------------------===//
  230. //--- IntervalTree ----//
  231. //===----------------------------------------------------------------------===//
  232. // Helper class template that is used by the IntervalTree to ensure that one
  233. // does instantiate using only fundamental and/or pointer types.
  234. template <typename T>
  235. using PointTypeIsValid = std::bool_constant<std::is_fundamental<T>::value>;
  236. template <typename T>
  237. using ValueTypeIsValid = std::bool_constant<std::is_fundamental<T>::value ||
  238. std::is_pointer<T>::value>;
  239. template <typename PointT, typename ValueT,
  240. typename DataT = IntervalData<PointT, ValueT>>
  241. class IntervalTree {
  242. static_assert(PointTypeIsValid<PointT>::value,
  243. "PointT must be a fundamental type");
  244. static_assert(ValueTypeIsValid<ValueT>::value,
  245. "ValueT must be a fundamental or pointer type");
  246. public:
  247. using PointType = PointT;
  248. using ValueType = ValueT;
  249. using DataType = DataT;
  250. using Allocator = BumpPtrAllocator;
  251. enum class Sorting { Ascending, Descending };
  252. using IntervalReferences = SmallVector<const DataType *, 4>;
  253. private:
  254. using IntervalVector = SmallVector<DataType, 4>;
  255. using PointsVector = SmallVector<PointType, 4>;
  256. class IntervalNode {
  257. PointType MiddlePoint; // MP - Middle point.
  258. IntervalNode *Left = nullptr; // LS - Left subtree.
  259. IntervalNode *Right = nullptr; // RS - Right subtree.
  260. unsigned BucketIntervalsStart = 0; // Starting index in global bucket.
  261. unsigned BucketIntervalsSize = 0; // Size of bucket.
  262. public:
  263. PointType middle() const { return MiddlePoint; }
  264. unsigned start() const { return BucketIntervalsStart; }
  265. unsigned size() const { return BucketIntervalsSize; }
  266. IntervalNode(PointType Point, unsigned Start)
  267. : MiddlePoint(Point), BucketIntervalsStart(Start) {}
  268. friend IntervalTree;
  269. };
  270. Allocator &NodeAllocator; // Allocator used for creating interval nodes.
  271. IntervalNode *Root = nullptr; // Interval tree root.
  272. IntervalVector Intervals; // Storage for each interval and all of the fields
  273. // point back into it.
  274. PointsVector EndPoints; // Sorted left and right points of all the intervals.
  275. // These vectors provide storage that nodes carve buckets of overlapping
  276. // intervals out of. All intervals are recorded on each vector.
  277. // The bucket with the intervals associated to a node, is determined by
  278. // the fields 'BucketIntervalStart' and 'BucketIntervalSize' in the node.
  279. // The buckets in the first vector are sorted in ascending order using
  280. // the left value and the buckets in the second vector are sorted in
  281. // descending order using the right value. Every interval in a bucket
  282. // contains the middle point for the node.
  283. IntervalReferences IntervalsLeft; // Intervals to the left of middle point.
  284. IntervalReferences IntervalsRight; // Intervals to the right of middle point.
  285. // Working vector used during the tree creation to sort the intervals. It is
  286. // cleared once the tree is created.
  287. IntervalReferences References;
  288. /// Recursively delete the constructed tree.
  289. void deleteTree(IntervalNode *Node) {
  290. if (Node) {
  291. deleteTree(Node->Left);
  292. deleteTree(Node->Right);
  293. Node->~IntervalNode();
  294. NodeAllocator.Deallocate(Node);
  295. }
  296. }
  297. /// Print the interval list (left and right) for a given \a Node.
  298. static void printList(raw_ostream &OS, IntervalReferences &IntervalSet,
  299. unsigned Start, unsigned Size, bool HexFormat = true) {
  300. assert(Start + Size <= IntervalSet.size() &&
  301. "Start + Size must be in bounds of the IntervalSet");
  302. const char *Format = HexFormat ? "[0x%08x,0x%08x] " : "[%2d,%2d] ";
  303. if (Size) {
  304. for (unsigned Position = Start; Position < Start + Size; ++Position)
  305. OS << format(Format, IntervalSet[Position]->left(),
  306. IntervalSet[Position]->right());
  307. } else {
  308. OS << "[]";
  309. }
  310. OS << "\n";
  311. }
  312. /// Print an interval tree \a Node.
  313. void printNode(raw_ostream &OS, unsigned Level, IntervalNode *Node,
  314. bool HexFormat = true) {
  315. const char *Format = HexFormat ? "MP:0x%08x " : "MP:%2d ";
  316. auto PrintNodeData = [&](StringRef Text, IntervalReferences &IntervalSet) {
  317. OS << format("%5d: ", Level);
  318. OS.indent(Level * 2);
  319. OS << format(Format, Node->middle()) << Text << " ";
  320. printList(OS, IntervalSet, Node->start(), Node->size(), HexFormat);
  321. };
  322. PrintNodeData("IR", IntervalsRight);
  323. PrintNodeData("IL", IntervalsLeft);
  324. }
  325. /// Recursively print all the interval nodes.
  326. void printTree(raw_ostream &OS, unsigned Level, IntervalNode *Node,
  327. bool HexFormat = true) {
  328. if (Node) {
  329. printNode(OS, Level, Node, HexFormat);
  330. ++Level;
  331. printTree(OS, Level, Node->Left, HexFormat);
  332. printTree(OS, Level, Node->Right, HexFormat);
  333. }
  334. }
  335. /// Recursively construct the interval tree.
  336. /// IntervalsSize: Number of intervals that have been processed and it will
  337. /// be used as the start for the intervals bucket for a node.
  338. /// PointsBeginIndex, PointsEndIndex: Determine the range into the EndPoints
  339. /// vector of end points to be processed.
  340. /// ReferencesBeginIndex, ReferencesSize: Determine the range into the
  341. /// intervals being processed.
  342. IntervalNode *createTree(unsigned &IntervalsSize, int PointsBeginIndex,
  343. int PointsEndIndex, int ReferencesBeginIndex,
  344. int ReferencesSize) {
  345. // We start by taking the entire range of all the intervals and dividing
  346. // it in half at x_middle (in practice, x_middle should be picked to keep
  347. // the tree relatively balanced).
  348. // This gives three sets of intervals, those completely to the left of
  349. // x_middle which we'll call S_left, those completely to the right of
  350. // x_middle which we'll call S_right, and those overlapping x_middle
  351. // which we'll call S_middle.
  352. // The intervals in S_left and S_right are recursively divided in the
  353. // same manner until there are no intervals remaining.
  354. if (PointsBeginIndex > PointsEndIndex ||
  355. ReferencesBeginIndex >= ReferencesSize)
  356. return nullptr;
  357. int MiddleIndex = (PointsBeginIndex + PointsEndIndex) / 2;
  358. PointType MiddlePoint = EndPoints[MiddleIndex];
  359. unsigned NewBucketStart = IntervalsSize;
  360. unsigned NewBucketSize = 0;
  361. int ReferencesRightIndex = ReferencesSize;
  362. IntervalNode *Root =
  363. new (NodeAllocator) IntervalNode(MiddlePoint, NewBucketStart);
  364. // A quicksort implementation where all the intervals that overlap
  365. // with the pivot are put into the "bucket", and "References" is the
  366. // partition space where we recursively sort the remaining intervals.
  367. for (int Index = ReferencesBeginIndex; Index < ReferencesRightIndex;) {
  368. // Current interval contains the middle point.
  369. if (References[Index]->contains(MiddlePoint)) {
  370. IntervalsLeft[IntervalsSize] = References[Index];
  371. IntervalsRight[IntervalsSize] = References[Index];
  372. ++IntervalsSize;
  373. Root->BucketIntervalsSize = ++NewBucketSize;
  374. if (Index < --ReferencesRightIndex)
  375. std::swap(References[Index], References[ReferencesRightIndex]);
  376. if (ReferencesRightIndex < --ReferencesSize)
  377. std::swap(References[ReferencesRightIndex],
  378. References[ReferencesSize]);
  379. continue;
  380. }
  381. if (References[Index]->left() > MiddlePoint) {
  382. if (Index < --ReferencesRightIndex)
  383. std::swap(References[Index], References[ReferencesRightIndex]);
  384. continue;
  385. }
  386. ++Index;
  387. }
  388. // Sort intervals on the left and right of the middle point.
  389. if (NewBucketSize > 1) {
  390. // Sort the intervals in ascending order by their beginning point.
  391. std::stable_sort(IntervalsLeft.begin() + NewBucketStart,
  392. IntervalsLeft.begin() + NewBucketStart + NewBucketSize,
  393. [](const DataType *LHS, const DataType *RHS) {
  394. return LHS->left() < RHS->left();
  395. });
  396. // Sort the intervals in descending order by their ending point.
  397. std::stable_sort(IntervalsRight.begin() + NewBucketStart,
  398. IntervalsRight.begin() + NewBucketStart + NewBucketSize,
  399. [](const DataType *LHS, const DataType *RHS) {
  400. return LHS->right() > RHS->right();
  401. });
  402. }
  403. if (PointsBeginIndex <= MiddleIndex - 1) {
  404. Root->Left = createTree(IntervalsSize, PointsBeginIndex, MiddleIndex - 1,
  405. ReferencesBeginIndex, ReferencesRightIndex);
  406. }
  407. if (MiddleIndex + 1 <= PointsEndIndex) {
  408. Root->Right = createTree(IntervalsSize, MiddleIndex + 1, PointsEndIndex,
  409. ReferencesRightIndex, ReferencesSize);
  410. }
  411. return Root;
  412. }
  413. public:
  414. class find_iterator {
  415. public:
  416. using iterator_category = std::forward_iterator_tag;
  417. using value_type = DataType;
  418. using difference_type = DataType;
  419. using pointer = DataType *;
  420. using reference = DataType &;
  421. private:
  422. const IntervalReferences *AscendingBuckets = nullptr;
  423. const IntervalReferences *DescendingBuckets = nullptr;
  424. // Current node and index while traversing the intervals that contain
  425. // the reference point.
  426. IntervalNode *Node = nullptr;
  427. PointType Point;
  428. unsigned Index = 0;
  429. // For the current node, check if we have intervals that contain the
  430. // reference point. We return when the node does have intervals that
  431. // contain such point. Otherwise we keep descending on that branch.
  432. void initNode() {
  433. Index = 0;
  434. while (Node) {
  435. // Return if the reference point is the same as the middle point or
  436. // the current node doesn't have any intervals at all.
  437. if (Point == Node->middle()) {
  438. if (Node->size() == 0) {
  439. // No intervals that contain the reference point.
  440. Node = nullptr;
  441. }
  442. return;
  443. }
  444. if (Point < Node->middle()) {
  445. // The reference point can be at the left or right of the middle
  446. // point. Return if the current node has intervals that contain the
  447. // reference point; otherwise descend on the respective branch.
  448. if (Node->size() && (*AscendingBuckets)[Node->start()]->left(Point)) {
  449. return;
  450. }
  451. Node = Node->Left;
  452. } else {
  453. if (Node->size() &&
  454. (*DescendingBuckets)[Node->start()]->right(Point)) {
  455. return;
  456. }
  457. Node = Node->Right;
  458. }
  459. }
  460. }
  461. // Given the current node (which was initialized by initNode), move to
  462. // the next interval in the list of intervals that contain the reference
  463. // point. Otherwise move to the next node, as the intervals contained
  464. // in that node, can contain the reference point.
  465. void nextInterval() {
  466. // If there are available intervals that contain the reference point,
  467. // traverse them; otherwise move to the left or right node, depending
  468. // on the middle point value.
  469. if (++Index < Node->size()) {
  470. if (Node->middle() == Point)
  471. return;
  472. if (Point < Node->middle()) {
  473. // Reference point is on the left.
  474. if (!(*AscendingBuckets)[Node->start() + Index]->left(Point)) {
  475. // The intervals don't contain the reference point. Move to the
  476. // next node, preserving the descending order.
  477. Node = Node->Left;
  478. initNode();
  479. }
  480. } else {
  481. // Reference point is on the right.
  482. if (!(*DescendingBuckets)[Node->start() + Index]->right(Point)) {
  483. // The intervals don't contain the reference point. Move to the
  484. // next node, preserving the ascending order.
  485. Node = Node->Right;
  486. initNode();
  487. }
  488. }
  489. } else {
  490. // We have traversed all the intervals in the current node.
  491. if (Point == Node->middle()) {
  492. Node = nullptr;
  493. Index = 0;
  494. return;
  495. }
  496. // Select a branch based on the middle point.
  497. Node = Point < Node->middle() ? Node->Left : Node->Right;
  498. initNode();
  499. }
  500. }
  501. find_iterator() = default;
  502. explicit find_iterator(const IntervalReferences *Left,
  503. const IntervalReferences *Right, IntervalNode *Node,
  504. PointType Point)
  505. : AscendingBuckets(Left), DescendingBuckets(Right), Node(Node),
  506. Point(Point), Index(0) {
  507. initNode();
  508. }
  509. const DataType *current() const {
  510. return (Point <= Node->middle())
  511. ? (*AscendingBuckets)[Node->start() + Index]
  512. : (*DescendingBuckets)[Node->start() + Index];
  513. }
  514. public:
  515. find_iterator &operator++() {
  516. nextInterval();
  517. return *this;
  518. }
  519. find_iterator operator++(int) {
  520. find_iterator Iter(*this);
  521. nextInterval();
  522. return Iter;
  523. }
  524. /// Dereference operators.
  525. const DataType *operator->() const { return current(); }
  526. const DataType &operator*() const { return *(current()); }
  527. /// Comparison operators.
  528. friend bool operator==(const find_iterator &LHS, const find_iterator &RHS) {
  529. return (!LHS.Node && !RHS.Node && !LHS.Index && !RHS.Index) ||
  530. (LHS.Point == RHS.Point && LHS.Node == RHS.Node &&
  531. LHS.Index == RHS.Index);
  532. }
  533. friend bool operator!=(const find_iterator &LHS, const find_iterator &RHS) {
  534. return !(LHS == RHS);
  535. }
  536. friend IntervalTree;
  537. };
  538. private:
  539. find_iterator End;
  540. public:
  541. explicit IntervalTree(Allocator &NodeAllocator)
  542. : NodeAllocator(NodeAllocator) {}
  543. ~IntervalTree() { clear(); }
  544. /// Return true when no intervals are mapped.
  545. bool empty() const { return Root == nullptr; }
  546. /// Remove all entries.
  547. void clear() {
  548. deleteTree(Root);
  549. Root = nullptr;
  550. Intervals.clear();
  551. IntervalsLeft.clear();
  552. IntervalsRight.clear();
  553. EndPoints.clear();
  554. }
  555. /// Add a mapping of [Left;Right] to \a Value.
  556. void insert(PointType Left, PointType Right, ValueType Value) {
  557. assert(empty() && "Invalid insertion. Interval tree already constructed.");
  558. Intervals.emplace_back(Left, Right, Value);
  559. }
  560. /// Return all the intervals in their natural tree location, that
  561. /// contain the given point.
  562. IntervalReferences getContaining(PointType Point) const {
  563. assert(!empty() && "Interval tree it is not constructed.");
  564. IntervalReferences IntervalSet;
  565. for (find_iterator Iter = find(Point), E = find_end(); Iter != E; ++Iter)
  566. IntervalSet.push_back(const_cast<DataType *>(&(*Iter)));
  567. return IntervalSet;
  568. }
  569. /// Sort the given intervals using the following sort options:
  570. /// Ascending: return the intervals with the smallest at the front.
  571. /// Descending: return the intervals with the biggest at the front.
  572. static void sortIntervals(IntervalReferences &IntervalSet, Sorting Sort) {
  573. std::stable_sort(IntervalSet.begin(), IntervalSet.end(),
  574. [Sort](const DataType *RHS, const DataType *LHS) {
  575. return Sort == Sorting::Ascending
  576. ? (LHS->right() - LHS->left()) >
  577. (RHS->right() - RHS->left())
  578. : (LHS->right() - LHS->left()) <
  579. (RHS->right() - RHS->left());
  580. });
  581. }
  582. /// Print the interval tree.
  583. /// When \a HexFormat is true, the interval tree interval ranges and
  584. /// associated values are printed in hexadecimal format.
  585. void print(raw_ostream &OS, bool HexFormat = true) {
  586. printTree(OS, 0, Root, HexFormat);
  587. }
  588. /// Create the interval tree.
  589. void create() {
  590. assert(empty() && "Interval tree already constructed.");
  591. // Sorted vector of unique end points values of all the intervals.
  592. // Records references to the collected intervals.
  593. SmallVector<PointType, 4> Points;
  594. for (const DataType &Data : Intervals) {
  595. Points.push_back(Data.left());
  596. Points.push_back(Data.right());
  597. References.push_back(std::addressof(Data));
  598. }
  599. std::stable_sort(Points.begin(), Points.end());
  600. auto Last = std::unique(Points.begin(), Points.end());
  601. Points.erase(Last, Points.end());
  602. EndPoints.assign(Points.begin(), Points.end());
  603. IntervalsLeft.resize(Intervals.size());
  604. IntervalsRight.resize(Intervals.size());
  605. // Given a set of n intervals, construct a data structure so that
  606. // we can efficiently retrieve all intervals overlapping another
  607. // interval or point.
  608. unsigned IntervalsSize = 0;
  609. Root =
  610. createTree(IntervalsSize, /*PointsBeginIndex=*/0, EndPoints.size() - 1,
  611. /*ReferencesBeginIndex=*/0, References.size());
  612. // Save to clear this storage, as it used only to sort the intervals.
  613. References.clear();
  614. }
  615. /// Iterator to start a find operation; it returns find_end() if the
  616. /// tree has not been built.
  617. /// There is no support to iterate over all the elements of the tree.
  618. find_iterator find(PointType Point) const {
  619. return empty()
  620. ? find_end()
  621. : find_iterator(&IntervalsLeft, &IntervalsRight, Root, Point);
  622. }
  623. /// Iterator to end find operation.
  624. find_iterator find_end() const { return End; }
  625. };
  626. } // namespace llvm
  627. #endif // LLVM_ADT_INTERVALTREE_H
  628. #ifdef __GNUC__
  629. #pragma GCC diagnostic pop
  630. #endif