Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:07

0001 //===-- IntervalTree.h ------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file implements an interval tree.
0010 //
0011 // Further information:
0012 // https://en.wikipedia.org/wiki/Interval_tree
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_ADT_INTERVALTREE_H
0017 #define LLVM_ADT_INTERVALTREE_H
0018 
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/Support/Allocator.h"
0021 #include "llvm/Support/Format.h"
0022 #include "llvm/Support/raw_ostream.h"
0023 #include <algorithm>
0024 #include <cassert>
0025 #include <iterator>
0026 
0027 // IntervalTree is a light tree data structure to hold intervals. It allows
0028 // finding all intervals that overlap with any given point. At this time,
0029 // it does not support any deletion or rebalancing operations.
0030 //
0031 // The IntervalTree is designed to be set up once, and then queried without
0032 // any further additions.
0033 //
0034 // Synopsis:
0035 //   Closed intervals delimited by PointT objects are mapped to ValueT objects.
0036 //
0037 // Restrictions:
0038 //   PointT must be a fundamental type.
0039 //   ValueT must be a fundamental or pointer type.
0040 //
0041 // template <typename PointT, typename ValueT, typename DataT>
0042 // class IntervalTree {
0043 // public:
0044 //
0045 //   IntervalTree();
0046 //   ~IntervalTree():
0047 //
0048 //   using IntervalReferences = SmallVector<IntervalData *>;
0049 //
0050 //   void create();
0051 //   void insert(PointT Left, PointT Right, ValueT Value);
0052 //
0053 //   IntervalReferences getContaining(PointT Point);
0054 //   static void sortIntervals(IntervalReferences &Intervals, Sorting Sort);
0055 //
0056 //   find_iterator begin(PointType Point) const;
0057 //   find_iterator end() const;
0058 //
0059 //   bool empty() const;
0060 //   void clear();
0061 //
0062 //   void print(raw_ostream &OS, bool HexFormat = true);
0063 // };
0064 //
0065 //===----------------------------------------------------------------------===//
0066 //
0067 // In the below given dataset
0068 //
0069 //   [a, b] <- (x)
0070 //
0071 // 'a' and 'b' describe a range and 'x' the value for that interval.
0072 //
0073 // The following data are purely for illustrative purposes:
0074 //
0075 // [30, 35] <- (3035),    [39, 50] <- (3950),    [55, 61] <- (5561),
0076 // [31, 56] <- (3156),    [12, 21] <- (1221),    [25, 41] <- (2541),
0077 // [49, 65] <- (4965),    [71, 79] <- (7179),    [11, 16] <- (1116),
0078 // [20, 30] <- (2030),    [36, 54] <- (3654),    [60, 70] <- (6070),
0079 // [74, 80] <- (7480),    [15, 40] <- (1540),    [43, 43] <- (4343),
0080 // [50, 75] <- (5075),    [10, 85] <- (1085)
0081 //
0082 // The data represents a set of overlapping intervals:
0083 //
0084 //                    30--35  39------------50  55----61
0085 //                      31------------------------56
0086 //     12--------21 25------------41      49-------------65   71-----79
0087 //   11----16  20-----30    36----------------54    60------70  74---- 80
0088 //       15---------------------40  43--43  50--------------------75
0089 // 10----------------------------------------------------------------------85
0090 //
0091 // The items are stored in a binary tree with each node storing:
0092 //
0093 // MP: A middle point.
0094 // IL: All intervals whose left value are completely to the left of the middle
0095 //     point. They are sorted in ascending order by their beginning point.
0096 // IR: All intervals whose right value are completely to the right of the
0097 //     middle point. They are sorted in descending order by their ending point.
0098 // LS: Left subtree.
0099 // RS: Right subtree.
0100 //
0101 // As IL and IR will contain the same intervals, in order to optimize space,
0102 // instead of storing intervals on each node, we use two vectors that will
0103 // contain the intervals described by IL and IR. Each node will contain an
0104 // index into that vector (global bucket), to indicate the beginning of the
0105 // intervals assigned to the node.
0106 //
0107 // The following is the output from print():
0108 //
0109 // 0: MP:43 IR [10,85] [31,56] [36,54] [39,50] [43,43]
0110 // 0: MP:43 IL [10,85] [31,56] [36,54] [39,50] [43,43]
0111 // 1:   MP:25 IR [25,41] [15,40] [20,30]
0112 // 1:   MP:25 IL [15,40] [20,30] [25,41]
0113 // 2:     MP:15 IR [12,21] [11,16]
0114 // 2:     MP:15 IL [11,16] [12,21]
0115 // 2:     MP:36 IR []
0116 // 2:     MP:36 IL []
0117 // 3:       MP:31 IR [30,35]
0118 // 3:       MP:31 IL [30,35]
0119 // 1:   MP:61 IR [50,75] [60,70] [49,65] [55,61]
0120 // 1:   MP:61 IL [49,65] [50,75] [55,61] [60,70]
0121 // 2:     MP:74 IR [74,80] [71,79]
0122 // 2:     MP:74 IL [71,79] [74,80]
0123 //
0124 // with:
0125 //    0: Root Node.
0126 //   MP: Middle point.
0127 //   IL: Intervals to the left (in ascending order by beginning point).
0128 //   IR: Intervals to the right (in descending order by ending point).
0129 //
0130 //                                    Root
0131 //                                      |
0132 //                                      V
0133 //                       +------------MP:43------------+
0134 //                       |            IL IR            |
0135 //                       |       [10,85] [10,85]       |
0136 //                    LS |       [31,56] [31,56]       | RS
0137 //                       |       [36,54] [36,54]       |
0138 //                       |       [39,50] [39,50]       |
0139 //                       |       [43,43] [43,43]       |
0140 //                       V                             V
0141 //        +------------MP:25------------+            MP:61------------+
0142 //        |            IL IR            |            IL IR            |
0143 //        |       [15,40] [25,41]       |       [49,65] [50,75]       |
0144 //     LS |       [20,30] [15,40]       | RS    [50,75] [60,70]       | RS
0145 //        |       [25,41] [20,30]       |       [55,61] [49,65]       |
0146 //        |                             |       [60,70] [55,61]       |
0147 //        V                             V                             V
0148 //      MP:15                 +-------MP:36                         MP:74
0149 //      IL IR                 |       IL IR                         IL IR
0150 // [11,16] [12,21]         LS |       [] []                    [71,79] [74,80]
0151 // [12,21] [11,16]            |                                [74,80] [71,79]
0152 //                            V
0153 //                          MP:31
0154 //                          IL IR
0155 //                     [30,35] [30,35]
0156 //
0157 // The creation of an interval tree is done in 2 steps:
0158 // 1) Insert the interval items by calling
0159 //    void insert(PointT Left, PointT Right, ValueT Value);
0160 //    Left, Right: the interval left and right limits.
0161 //    Value: the data associated with that specific interval.
0162 //
0163 // 2) Create the interval tree by calling
0164 //    void create();
0165 //
0166 // Once the tree is created, it is switched to query mode.
0167 // Query the tree by using iterators or container.
0168 //
0169 // a) Iterators over intervals overlapping the given point with very weak
0170 //    ordering guarantees.
0171 //    find_iterator begin(PointType Point) const;
0172 //    find_iterator end() const;
0173 //    Point: a target point to be tested for inclusion in any interval.
0174 //
0175 // b) Container:
0176 //    IntervalReferences getContaining(PointT Point);
0177 //    Point: a target point to be tested for inclusion in any interval.
0178 //    Returns vector with all the intervals containing the target point.
0179 //
0180 // The returned intervals are in their natural tree location. They can
0181 // be sorted:
0182 //
0183 // static void sortIntervals(IntervalReferences &Intervals, Sorting Sort);
0184 //
0185 // Ability to print the constructed interval tree:
0186 //   void print(raw_ostream &OS, bool HexFormat = true);
0187 // Display the associated data in hexadecimal format.
0188 
0189 namespace llvm {
0190 
0191 //===----------------------------------------------------------------------===//
0192 //---                          IntervalData                               ----//
0193 //===----------------------------------------------------------------------===//
0194 /// An interval data composed by a \a Left and \a Right points and an
0195 /// associated \a Value.
0196 /// \a PointT corresponds to the interval endpoints type.
0197 /// \a ValueT corresponds to the interval value type.
0198 template <typename PointT, typename ValueT> class IntervalData {
0199 protected:
0200   using PointType = PointT;
0201   using ValueType = ValueT;
0202 
0203 private:
0204   PointType Left;
0205   PointType Right;
0206   ValueType Value;
0207 
0208 public:
0209   IntervalData() = delete;
0210   IntervalData(PointType Left, PointType Right, ValueType Value)
0211       : Left(Left), Right(Right), Value(Value) {
0212     assert(Left <= Right && "'Left' must be less or equal to 'Right'");
0213   }
0214   virtual ~IntervalData() = default;
0215   PointType left() const { return Left; }
0216   PointType right() const { return Right; }
0217   ValueType value() const { return Value; }
0218 
0219   /// Return true if \a Point is inside the left bound of closed interval \a
0220   /// [Left;Right]. This is Left <= Point for closed intervals.
0221   bool left(const PointType &Point) const { return left() <= Point; }
0222 
0223   /// Return true if \a Point is inside the right bound of closed interval \a
0224   /// [Left;Right]. This is Point <= Right for closed intervals.
0225   bool right(const PointType &Point) const { return Point <= right(); }
0226 
0227   /// Return true when \a Point is contained in interval \a [Left;Right].
0228   /// This is Left <= Point <= Right for closed intervals.
0229   bool contains(const PointType &Point) const {
0230     return left(Point) && right(Point);
0231   }
0232 };
0233 
0234 //===----------------------------------------------------------------------===//
0235 //---                          IntervalTree                               ----//
0236 //===----------------------------------------------------------------------===//
0237 // Helper class template that is used by the IntervalTree to ensure that one
0238 // does instantiate using only fundamental and/or pointer types.
0239 template <typename T>
0240 using PointTypeIsValid = std::bool_constant<std::is_fundamental<T>::value>;
0241 
0242 template <typename T>
0243 using ValueTypeIsValid = std::bool_constant<std::is_fundamental<T>::value ||
0244                                             std::is_pointer<T>::value>;
0245 
0246 template <typename PointT, typename ValueT,
0247           typename DataT = IntervalData<PointT, ValueT>>
0248 class IntervalTree {
0249   static_assert(PointTypeIsValid<PointT>::value,
0250                 "PointT must be a fundamental type");
0251   static_assert(ValueTypeIsValid<ValueT>::value,
0252                 "ValueT must be a fundamental or pointer type");
0253 
0254 public:
0255   using PointType = PointT;
0256   using ValueType = ValueT;
0257   using DataType = DataT;
0258   using Allocator = BumpPtrAllocator;
0259 
0260   enum class Sorting { Ascending, Descending };
0261   using IntervalReferences = SmallVector<const DataType *, 4>;
0262 
0263 private:
0264   using IntervalVector = SmallVector<DataType, 4>;
0265   using PointsVector = SmallVector<PointType, 4>;
0266 
0267   class IntervalNode {
0268     PointType MiddlePoint;             // MP - Middle point.
0269     IntervalNode *Left = nullptr;      // LS - Left subtree.
0270     IntervalNode *Right = nullptr;     // RS - Right subtree.
0271     unsigned BucketIntervalsStart = 0; // Starting index in global bucket.
0272     unsigned BucketIntervalsSize = 0;  // Size of bucket.
0273 
0274   public:
0275     PointType middle() const { return MiddlePoint; }
0276     unsigned start() const { return BucketIntervalsStart; }
0277     unsigned size() const { return BucketIntervalsSize; }
0278 
0279     IntervalNode(PointType Point, unsigned Start)
0280         : MiddlePoint(Point), BucketIntervalsStart(Start) {}
0281 
0282     friend IntervalTree;
0283   };
0284 
0285   Allocator &NodeAllocator;     // Allocator used for creating interval nodes.
0286   IntervalNode *Root = nullptr; // Interval tree root.
0287   IntervalVector Intervals; // Storage for each interval and all of the fields
0288                             // point back into it.
0289   PointsVector EndPoints; // Sorted left and right points of all the intervals.
0290 
0291   // These vectors provide storage that nodes carve buckets of overlapping
0292   // intervals out of. All intervals are recorded on each vector.
0293   // The bucket with the intervals associated to a node, is determined by
0294   // the fields 'BucketIntervalStart' and 'BucketIntervalSize' in the node.
0295   // The buckets in the first vector are sorted in ascending order using
0296   // the left value and the buckets in the second vector are sorted in
0297   // descending order using the right value. Every interval in a bucket
0298   // contains the middle point for the node.
0299   IntervalReferences IntervalsLeft;  // Intervals to the left of middle point.
0300   IntervalReferences IntervalsRight; // Intervals to the right of middle point.
0301 
0302   // Working vector used during the tree creation to sort the intervals. It is
0303   // cleared once the tree is created.
0304   IntervalReferences References;
0305 
0306   /// Recursively delete the constructed tree.
0307   void deleteTree(IntervalNode *Node) {
0308     if (Node) {
0309       deleteTree(Node->Left);
0310       deleteTree(Node->Right);
0311       Node->~IntervalNode();
0312       NodeAllocator.Deallocate(Node);
0313     }
0314   }
0315 
0316   /// Print the interval list (left and right) for a given \a Node.
0317   static void printList(raw_ostream &OS, IntervalReferences &IntervalSet,
0318                         unsigned Start, unsigned Size, bool HexFormat = true) {
0319     assert(Start + Size <= IntervalSet.size() &&
0320            "Start + Size must be in bounds of the IntervalSet");
0321     const char *Format = HexFormat ? "[0x%08x,0x%08x] " : "[%2d,%2d] ";
0322     if (Size) {
0323       for (unsigned Position = Start; Position < Start + Size; ++Position)
0324         OS << format(Format, IntervalSet[Position]->left(),
0325                      IntervalSet[Position]->right());
0326     } else {
0327       OS << "[]";
0328     }
0329     OS << "\n";
0330   }
0331 
0332   /// Print an interval tree \a Node.
0333   void printNode(raw_ostream &OS, unsigned Level, IntervalNode *Node,
0334                  bool HexFormat = true) {
0335     const char *Format = HexFormat ? "MP:0x%08x " : "MP:%2d ";
0336     auto PrintNodeData = [&](StringRef Text, IntervalReferences &IntervalSet) {
0337       OS << format("%5d: ", Level);
0338       OS.indent(Level * 2);
0339       OS << format(Format, Node->middle()) << Text << " ";
0340       printList(OS, IntervalSet, Node->start(), Node->size(), HexFormat);
0341     };
0342 
0343     PrintNodeData("IR", IntervalsRight);
0344     PrintNodeData("IL", IntervalsLeft);
0345   }
0346 
0347   /// Recursively print all the interval nodes.
0348   void printTree(raw_ostream &OS, unsigned Level, IntervalNode *Node,
0349                  bool HexFormat = true) {
0350     if (Node) {
0351       printNode(OS, Level, Node, HexFormat);
0352       ++Level;
0353       printTree(OS, Level, Node->Left, HexFormat);
0354       printTree(OS, Level, Node->Right, HexFormat);
0355     }
0356   }
0357 
0358   /// Recursively construct the interval tree.
0359   /// IntervalsSize: Number of intervals that have been processed and it will
0360   /// be used as the start for the intervals bucket for a node.
0361   /// PointsBeginIndex, PointsEndIndex: Determine the range into the EndPoints
0362   /// vector of end points to be processed.
0363   /// ReferencesBeginIndex, ReferencesSize: Determine the range into the
0364   /// intervals being processed.
0365   IntervalNode *createTree(unsigned &IntervalsSize, int PointsBeginIndex,
0366                            int PointsEndIndex, int ReferencesBeginIndex,
0367                            int ReferencesSize) {
0368     // We start by taking the entire range of all the intervals and dividing
0369     // it in half at x_middle (in practice, x_middle should be picked to keep
0370     // the tree relatively balanced).
0371     // This gives three sets of intervals, those completely to the left of
0372     // x_middle which we'll call S_left, those completely to the right of
0373     // x_middle which we'll call S_right, and those overlapping x_middle
0374     // which we'll call S_middle.
0375     // The intervals in S_left and S_right are recursively divided in the
0376     // same manner until there are no intervals remaining.
0377 
0378     if (PointsBeginIndex > PointsEndIndex ||
0379         ReferencesBeginIndex >= ReferencesSize)
0380       return nullptr;
0381 
0382     int MiddleIndex = (PointsBeginIndex + PointsEndIndex) / 2;
0383     PointType MiddlePoint = EndPoints[MiddleIndex];
0384 
0385     unsigned NewBucketStart = IntervalsSize;
0386     unsigned NewBucketSize = 0;
0387     int ReferencesRightIndex = ReferencesSize;
0388 
0389     IntervalNode *Root =
0390         new (NodeAllocator) IntervalNode(MiddlePoint, NewBucketStart);
0391 
0392     // A quicksort implementation where all the intervals that overlap
0393     // with the pivot are put into the "bucket", and "References" is the
0394     // partition space where we recursively sort the remaining intervals.
0395     for (int Index = ReferencesBeginIndex; Index < ReferencesRightIndex;) {
0396 
0397       // Current interval contains the middle point.
0398       if (References[Index]->contains(MiddlePoint)) {
0399         IntervalsLeft[IntervalsSize] = References[Index];
0400         IntervalsRight[IntervalsSize] = References[Index];
0401         ++IntervalsSize;
0402         Root->BucketIntervalsSize = ++NewBucketSize;
0403 
0404         if (Index < --ReferencesRightIndex)
0405           std::swap(References[Index], References[ReferencesRightIndex]);
0406         if (ReferencesRightIndex < --ReferencesSize)
0407           std::swap(References[ReferencesRightIndex],
0408                     References[ReferencesSize]);
0409         continue;
0410       }
0411 
0412       if (References[Index]->left() > MiddlePoint) {
0413         if (Index < --ReferencesRightIndex)
0414           std::swap(References[Index], References[ReferencesRightIndex]);
0415         continue;
0416       }
0417       ++Index;
0418     }
0419 
0420     // Sort intervals on the left and right of the middle point.
0421     if (NewBucketSize > 1) {
0422       // Sort the intervals in ascending order by their beginning point.
0423       std::stable_sort(IntervalsLeft.begin() + NewBucketStart,
0424                        IntervalsLeft.begin() + NewBucketStart + NewBucketSize,
0425                        [](const DataType *LHS, const DataType *RHS) {
0426                          return LHS->left() < RHS->left();
0427                        });
0428       // Sort the intervals in descending order by their ending point.
0429       std::stable_sort(IntervalsRight.begin() + NewBucketStart,
0430                        IntervalsRight.begin() + NewBucketStart + NewBucketSize,
0431                        [](const DataType *LHS, const DataType *RHS) {
0432                          return LHS->right() > RHS->right();
0433                        });
0434     }
0435 
0436     if (PointsBeginIndex <= MiddleIndex - 1) {
0437       Root->Left = createTree(IntervalsSize, PointsBeginIndex, MiddleIndex - 1,
0438                               ReferencesBeginIndex, ReferencesRightIndex);
0439     }
0440 
0441     if (MiddleIndex + 1 <= PointsEndIndex) {
0442       Root->Right = createTree(IntervalsSize, MiddleIndex + 1, PointsEndIndex,
0443                                ReferencesRightIndex, ReferencesSize);
0444     }
0445 
0446     return Root;
0447   }
0448 
0449 public:
0450   class find_iterator {
0451   public:
0452     using iterator_category = std::forward_iterator_tag;
0453     using value_type = DataType;
0454     using difference_type = DataType;
0455     using pointer = DataType *;
0456     using reference = DataType &;
0457 
0458   private:
0459     const IntervalReferences *AscendingBuckets = nullptr;
0460     const IntervalReferences *DescendingBuckets = nullptr;
0461 
0462     // Current node and index while traversing the intervals that contain
0463     // the reference point.
0464     IntervalNode *Node = nullptr;
0465     PointType Point = {};
0466     unsigned Index = 0;
0467 
0468     // For the current node, check if we have intervals that contain the
0469     // reference point. We return when the node does have intervals that
0470     // contain such point. Otherwise we keep descending on that branch.
0471     void initNode() {
0472       Index = 0;
0473       while (Node) {
0474         // Return if the reference point is the same as the middle point or
0475         // the current node doesn't have any intervals at all.
0476         if (Point == Node->middle()) {
0477           if (Node->size() == 0) {
0478             // No intervals that contain the reference point.
0479             Node = nullptr;
0480           }
0481           return;
0482         }
0483 
0484         if (Point < Node->middle()) {
0485           // The reference point can be at the left or right of the middle
0486           // point. Return if the current node has intervals that contain the
0487           // reference point; otherwise descend on the respective branch.
0488           if (Node->size() && (*AscendingBuckets)[Node->start()]->left(Point)) {
0489             return;
0490           }
0491           Node = Node->Left;
0492         } else {
0493           if (Node->size() &&
0494               (*DescendingBuckets)[Node->start()]->right(Point)) {
0495             return;
0496           }
0497           Node = Node->Right;
0498         }
0499       }
0500     }
0501 
0502     // Given the current node (which was initialized by initNode), move to
0503     // the next interval in the list of intervals that contain the reference
0504     // point. Otherwise move to the next node, as the intervals contained
0505     // in that node, can contain the reference point.
0506     void nextInterval() {
0507       // If there are available intervals that contain the reference point,
0508       // traverse them; otherwise move to the left or right node, depending
0509       // on the middle point value.
0510       if (++Index < Node->size()) {
0511         if (Node->middle() == Point)
0512           return;
0513         if (Point < Node->middle()) {
0514           // Reference point is on the left.
0515           if (!(*AscendingBuckets)[Node->start() + Index]->left(Point)) {
0516             // The intervals don't contain the reference point. Move to the
0517             // next node, preserving the descending order.
0518             Node = Node->Left;
0519             initNode();
0520           }
0521         } else {
0522           // Reference point is on the right.
0523           if (!(*DescendingBuckets)[Node->start() + Index]->right(Point)) {
0524             // The intervals don't contain the reference point. Move to the
0525             // next node, preserving the ascending order.
0526             Node = Node->Right;
0527             initNode();
0528           }
0529         }
0530       } else {
0531         // We have traversed all the intervals in the current node.
0532         if (Point == Node->middle()) {
0533           Node = nullptr;
0534           Index = 0;
0535           return;
0536         }
0537         // Select a branch based on the middle point.
0538         Node = Point < Node->middle() ? Node->Left : Node->Right;
0539         initNode();
0540       }
0541     }
0542 
0543     find_iterator() = default;
0544     explicit find_iterator(const IntervalReferences *Left,
0545                            const IntervalReferences *Right, IntervalNode *Node,
0546                            PointType Point)
0547         : AscendingBuckets(Left), DescendingBuckets(Right), Node(Node),
0548           Point(Point), Index(0) {
0549       initNode();
0550     }
0551 
0552     const DataType *current() const {
0553       return (Point <= Node->middle())
0554                  ? (*AscendingBuckets)[Node->start() + Index]
0555                  : (*DescendingBuckets)[Node->start() + Index];
0556     }
0557 
0558   public:
0559     find_iterator &operator++() {
0560       nextInterval();
0561       return *this;
0562     }
0563 
0564     find_iterator operator++(int) {
0565       find_iterator Iter(*this);
0566       nextInterval();
0567       return Iter;
0568     }
0569 
0570     /// Dereference operators.
0571     const DataType *operator->() const { return current(); }
0572     const DataType &operator*() const { return *(current()); }
0573 
0574     /// Comparison operators.
0575     friend bool operator==(const find_iterator &LHS, const find_iterator &RHS) {
0576       return (!LHS.Node && !RHS.Node && !LHS.Index && !RHS.Index) ||
0577              (LHS.Point == RHS.Point && LHS.Node == RHS.Node &&
0578               LHS.Index == RHS.Index);
0579     }
0580     friend bool operator!=(const find_iterator &LHS, const find_iterator &RHS) {
0581       return !(LHS == RHS);
0582     }
0583 
0584     friend IntervalTree;
0585   };
0586 
0587 private:
0588   find_iterator End;
0589 
0590 public:
0591   explicit IntervalTree(Allocator &NodeAllocator)
0592       : NodeAllocator(NodeAllocator) {}
0593   ~IntervalTree() { clear(); }
0594 
0595   /// Return true when no intervals are mapped.
0596   bool empty() const { return Root == nullptr; }
0597 
0598   /// Remove all entries.
0599   void clear() {
0600     deleteTree(Root);
0601     Root = nullptr;
0602     Intervals.clear();
0603     IntervalsLeft.clear();
0604     IntervalsRight.clear();
0605     EndPoints.clear();
0606   }
0607 
0608   /// Add a mapping of [Left;Right] to \a Value.
0609   void insert(PointType Left, PointType Right, ValueType Value) {
0610     assert(empty() && "Invalid insertion. Interval tree already constructed.");
0611     Intervals.emplace_back(Left, Right, Value);
0612   }
0613 
0614   /// Return all the intervals in their natural tree location, that
0615   /// contain the given point.
0616   IntervalReferences getContaining(PointType Point) const {
0617     assert(!empty() && "Interval tree it is not constructed.");
0618     IntervalReferences IntervalSet;
0619     for (find_iterator Iter = find(Point), E = find_end(); Iter != E; ++Iter)
0620       IntervalSet.push_back(const_cast<DataType *>(&(*Iter)));
0621     return IntervalSet;
0622   }
0623 
0624   /// Sort the given intervals using the following sort options:
0625   /// Ascending: return the intervals with the smallest at the front.
0626   /// Descending: return the intervals with the biggest at the front.
0627   static void sortIntervals(IntervalReferences &IntervalSet, Sorting Sort) {
0628     std::stable_sort(IntervalSet.begin(), IntervalSet.end(),
0629                      [Sort](const DataType *RHS, const DataType *LHS) {
0630                        return Sort == Sorting::Ascending
0631                                   ? (LHS->right() - LHS->left()) >
0632                                         (RHS->right() - RHS->left())
0633                                   : (LHS->right() - LHS->left()) <
0634                                         (RHS->right() - RHS->left());
0635                      });
0636   }
0637 
0638   /// Print the interval tree.
0639   /// When \a HexFormat is true, the interval tree interval ranges and
0640   /// associated values are printed in hexadecimal format.
0641   void print(raw_ostream &OS, bool HexFormat = true) {
0642     printTree(OS, 0, Root, HexFormat);
0643   }
0644 
0645   /// Create the interval tree.
0646   void create() {
0647     assert(empty() && "Interval tree already constructed.");
0648     // Sorted vector of unique end points values of all the intervals.
0649     // Records references to the collected intervals.
0650     SmallVector<PointType, 4> Points;
0651     for (const DataType &Data : Intervals) {
0652       Points.push_back(Data.left());
0653       Points.push_back(Data.right());
0654       References.push_back(std::addressof(Data));
0655     }
0656     std::stable_sort(Points.begin(), Points.end());
0657     auto Last = llvm::unique(Points);
0658     Points.erase(Last, Points.end());
0659 
0660     EndPoints.assign(Points.begin(), Points.end());
0661 
0662     IntervalsLeft.resize(Intervals.size());
0663     IntervalsRight.resize(Intervals.size());
0664 
0665     // Given a set of n intervals, construct a data structure so that
0666     // we can efficiently retrieve all intervals overlapping another
0667     // interval or point.
0668     unsigned IntervalsSize = 0;
0669     Root =
0670         createTree(IntervalsSize, /*PointsBeginIndex=*/0, EndPoints.size() - 1,
0671                    /*ReferencesBeginIndex=*/0, References.size());
0672 
0673     // Save to clear this storage, as it used only to sort the intervals.
0674     References.clear();
0675   }
0676 
0677   /// Iterator to start a find operation; it returns find_end() if the
0678   /// tree has not been built.
0679   /// There is no support to iterate over all the elements of the tree.
0680   find_iterator find(PointType Point) const {
0681     return empty()
0682                ? find_end()
0683                : find_iterator(&IntervalsLeft, &IntervalsRight, Root, Point);
0684   }
0685 
0686   /// Iterator to end find operation.
0687   find_iterator find_end() const { return End; }
0688 };
0689 
0690 } // namespace llvm
0691 
0692 #endif // LLVM_ADT_INTERVALTREE_H