Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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