1 //===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the few non-templated functions in IntervalMap.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/IntervalMap.h"
16 namespace IntervalMapImpl
{
18 void Path::replaceRoot(void *Root
, unsigned Size
, IdxPair Offsets
) {
19 assert(!path
.empty() && "Can't replace missing root");
20 path
.front() = Entry(Root
, Size
, Offsets
.first
);
21 path
.insert(path
.begin() + 1, Entry(subtree(0), Offsets
.second
));
24 NodeRef
Path::getLeftSibling(unsigned Level
) const {
25 // The root has no siblings.
29 // Go up the tree until we can go left.
30 unsigned l
= Level
- 1;
31 while (l
&& path
[l
].offset
== 0)
35 if (path
[l
].offset
== 0)
38 // NR is the subtree containing our left sibling.
39 NodeRef NR
= path
[l
].subtree(path
[l
].offset
- 1);
41 // Keep right all the way down.
42 for (++l
; l
!= Level
; ++l
)
43 NR
= NR
.subtree(NR
.size() - 1);
47 void Path::moveLeft(unsigned Level
) {
48 assert(Level
!= 0 && "Cannot move the root node");
50 // Go up the tree until we can go left.
54 while (path
[l
].offset
== 0) {
55 assert(l
!= 0 && "Cannot move beyond begin()");
58 } else if (height() < Level
)
59 // end() may have created a height=0 path.
60 path
.resize(Level
+ 1, Entry(nullptr, 0, 0));
62 // NR is the subtree containing our left sibling.
64 NodeRef NR
= subtree(l
);
66 // Get the rightmost node in the subtree.
67 for (++l
; l
!= Level
; ++l
) {
68 path
[l
] = Entry(NR
, NR
.size() - 1);
69 NR
= NR
.subtree(NR
.size() - 1);
71 path
[l
] = Entry(NR
, NR
.size() - 1);
74 NodeRef
Path::getRightSibling(unsigned Level
) const {
75 // The root has no siblings.
79 // Go up the tree until we can go right.
80 unsigned l
= Level
- 1;
81 while (l
&& atLastEntry(l
))
88 // NR is the subtree containing our right sibling.
89 NodeRef NR
= path
[l
].subtree(path
[l
].offset
+ 1);
91 // Keep left all the way down.
92 for (++l
; l
!= Level
; ++l
)
97 void Path::moveRight(unsigned Level
) {
98 assert(Level
!= 0 && "Cannot move the root node");
100 // Go up the tree until we can go right.
101 unsigned l
= Level
- 1;
102 while (l
&& atLastEntry(l
))
105 // NR is the subtree containing our right sibling. If we hit end(), we have
106 // offset(0) == node(0).size().
107 if (++path
[l
].offset
== path
[l
].size
)
109 NodeRef NR
= subtree(l
);
111 for (++l
; l
!= Level
; ++l
) {
112 path
[l
] = Entry(NR
, 0);
115 path
[l
] = Entry(NR
, 0);
119 IdxPair
distribute(unsigned Nodes
, unsigned Elements
, unsigned Capacity
,
120 const unsigned *CurSize
, unsigned NewSize
[],
121 unsigned Position
, bool Grow
) {
122 assert(Elements
+ Grow
<= Nodes
* Capacity
&& "Not enough room for elements");
123 assert(Position
<= Elements
&& "Invalid position");
127 // Trivial algorithm: left-leaning even distribution.
128 const unsigned PerNode
= (Elements
+ Grow
) / Nodes
;
129 const unsigned Extra
= (Elements
+ Grow
) % Nodes
;
130 IdxPair PosPair
= IdxPair(Nodes
, 0);
132 for (unsigned n
= 0; n
!= Nodes
; ++n
) {
133 Sum
+= NewSize
[n
] = PerNode
+ (n
< Extra
);
134 if (PosPair
.first
== Nodes
&& Sum
> Position
)
135 PosPair
= IdxPair(n
, Position
- (Sum
- NewSize
[n
]));
137 assert(Sum
== Elements
+ Grow
&& "Bad distribution sum");
139 // Subtract the Grow element that was added.
141 assert(PosPair
.first
< Nodes
&& "Bad algebra");
142 assert(NewSize
[PosPair
.first
] && "Too few elements to need Grow");
143 --NewSize
[PosPair
.first
];
148 for (unsigned n
= 0; n
!= Nodes
; ++n
) {
149 assert(NewSize
[n
] <= Capacity
&& "Overallocated node");
152 assert(Sum
== Elements
&& "Bad distribution sum");
158 } // namespace IntervalMapImpl