mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Move tree navigation to a new Path class that doesn't have to be a template.
The path also holds a reference to the root node, and that allows important iterator accessors like start() and stop() to have no conditional code. (When the compiler is clever enough to remove it.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120165 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20a00c4f80
commit
706da9d8ca
@ -403,7 +403,7 @@ public:
|
|||||||
/// subtree - Access the i'th subtree reference in a branch node.
|
/// subtree - Access the i'th subtree reference in a branch node.
|
||||||
/// This depends on branch nodes storing the NodeRef array as their first
|
/// This depends on branch nodes storing the NodeRef array as their first
|
||||||
/// member.
|
/// member.
|
||||||
NodeRef &subtree(unsigned i) {
|
NodeRef &subtree(unsigned i) const {
|
||||||
return reinterpret_cast<NodeRef*>(pip.getPointer())[i];
|
return reinterpret_cast<NodeRef*>(pip.getPointer())[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,6 +699,161 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//--- Path ---//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// A Path is used by iterators to represent a position in a B+-tree, and the
|
||||||
|
// path to get there from the root.
|
||||||
|
//
|
||||||
|
// The Path class also constains the tree navigation code that doesn't have to
|
||||||
|
// be templatized.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
class Path {
|
||||||
|
/// Entry - Each step in the path is a node pointer and an offset into that
|
||||||
|
/// node.
|
||||||
|
struct Entry {
|
||||||
|
void *node;
|
||||||
|
unsigned size;
|
||||||
|
unsigned offset;
|
||||||
|
|
||||||
|
Entry(void *Node, unsigned Size, unsigned Offset)
|
||||||
|
: node(Node), size(Size), offset(Offset) {}
|
||||||
|
|
||||||
|
Entry(NodeRef Node, unsigned Offset)
|
||||||
|
: node(&Node.subtree(0)), size(Node.size()), offset(Offset) {}
|
||||||
|
|
||||||
|
NodeRef &subtree(unsigned i) const {
|
||||||
|
return reinterpret_cast<NodeRef*>(node)[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// path - The path entries, path[0] is the root node, path.back() is a leaf.
|
||||||
|
SmallVector<Entry, 4> path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Node accessors.
|
||||||
|
template <typename NodeT> NodeT &node(unsigned Level) const {
|
||||||
|
return *reinterpret_cast<NodeT*>(path[Level].node);
|
||||||
|
}
|
||||||
|
unsigned size(unsigned Level) const { return path[Level].size; }
|
||||||
|
unsigned offset(unsigned Level) const { return path[Level].offset; }
|
||||||
|
unsigned &offset(unsigned Level) { return path[Level].offset; }
|
||||||
|
|
||||||
|
// Leaf accessors.
|
||||||
|
template <typename NodeT> NodeT &leaf() const {
|
||||||
|
return *reinterpret_cast<NodeT*>(path.back().node);
|
||||||
|
}
|
||||||
|
unsigned leafSize() const { return path.back().size; }
|
||||||
|
unsigned leafOffset() const { return path.back().offset; }
|
||||||
|
unsigned &leafOffset() { return path.back().offset; }
|
||||||
|
|
||||||
|
/// valid - Return true if path is at a valid node, not at end().
|
||||||
|
bool valid() const {
|
||||||
|
return !path.empty() && path.front().offset < path.front().size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// height - Return the height of the tree corresponding to this path.
|
||||||
|
/// This matches map->height in a full path.
|
||||||
|
unsigned height() const { return path.size() - 1; }
|
||||||
|
|
||||||
|
/// subtree - Get the subtree referenced from Level. When the path is
|
||||||
|
/// consistent, node(Level + 1) == subtree(Level).
|
||||||
|
/// @param Level 0..height-1. The leaves have no subtrees.
|
||||||
|
NodeRef &subtree(unsigned Level) const {
|
||||||
|
return path[Level].subtree(path[Level].offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// push - Add entry to path.
|
||||||
|
/// @param Node Node to add, should be subtree(path.size()-1).
|
||||||
|
/// @param Offset Offset into Node.
|
||||||
|
void push(NodeRef Node, unsigned Offset) {
|
||||||
|
path.push_back(Entry(Node, Offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// setSize - Set the size of a node both in the path and in the tree.
|
||||||
|
/// @param Level 0..height. Note that setting the root size won't change
|
||||||
|
/// map->rootSize.
|
||||||
|
/// @param Size New node size.
|
||||||
|
void setSize(unsigned Level, unsigned Size) {
|
||||||
|
path[Level].size = Size;
|
||||||
|
if (Level)
|
||||||
|
subtree(Level - 1).setSize(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// setRoot - Clear the path and set a new root node.
|
||||||
|
/// @param Node New root node.
|
||||||
|
/// @param Size New root size.
|
||||||
|
/// @param Offset Offset into root node.
|
||||||
|
void setRoot(void *Node, unsigned Size, unsigned Offset) {
|
||||||
|
path.clear();
|
||||||
|
path.push_back(Entry(Node, Size, Offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// replaceRoot - Replace the current root node with two new entries after the
|
||||||
|
/// tree height has increased.
|
||||||
|
/// @param Root The new root node.
|
||||||
|
/// @param Size Number of entries in the new root.
|
||||||
|
/// @param Offsets Offsets into the root and first branch nodes.
|
||||||
|
void replaceRoot(void *Root, unsigned Size, IdxPair Offsets);
|
||||||
|
|
||||||
|
/// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
|
||||||
|
/// @param Level Get the sibling to node(Level).
|
||||||
|
/// @return Left sibling, or NodeRef().
|
||||||
|
NodeRef getLeftSibling(unsigned Level) const;
|
||||||
|
|
||||||
|
/// moveLeft - Move path to the left sibling at Level. Leave nodes below Level
|
||||||
|
/// unaltered.
|
||||||
|
/// @param Level Move node(Level).
|
||||||
|
void moveLeft(unsigned Level);
|
||||||
|
|
||||||
|
/// fillLeft - Grow path to Height by taking leftmost branches.
|
||||||
|
/// @param Height The target height.
|
||||||
|
void fillLeft(unsigned Height) {
|
||||||
|
while (height() < Height)
|
||||||
|
push(subtree(height()), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
|
||||||
|
/// @param Level Get the sinbling to node(Level).
|
||||||
|
/// @return Left sibling, or NodeRef().
|
||||||
|
NodeRef getRightSibling(unsigned Level) const;
|
||||||
|
|
||||||
|
/// moveRight - Move path to the left sibling at Level. Leave nodes below
|
||||||
|
/// Level unaltered.
|
||||||
|
/// @param Level Move node(Level).
|
||||||
|
void moveRight(unsigned Level);
|
||||||
|
|
||||||
|
/// atLastBranch - Return true if the path is at the last branch of the node
|
||||||
|
/// at Level.
|
||||||
|
/// @param Level Node to examine.
|
||||||
|
bool atLastBranch(unsigned Level) const {
|
||||||
|
return path[Level].offset == path[Level].size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// legalizeForInsert - Prepare the path for an insertion at Level. When the
|
||||||
|
/// path is at end(), node(Level) may not be a legal node. legalizeForInsert
|
||||||
|
/// ensures that node(Level) is real by moving back to the last node at Level,
|
||||||
|
/// and setting offset(Level) to size(Level) if required.
|
||||||
|
/// @param Level The level where an insertion is about to take place.
|
||||||
|
void legalizeForInsert(unsigned Level) {
|
||||||
|
if (valid())
|
||||||
|
return;
|
||||||
|
moveLeft(Level);
|
||||||
|
++path[Level].offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void dump() const {
|
||||||
|
for (unsigned l = 0, e = path.size(); l != e; ++l)
|
||||||
|
errs() << l << ": " << path[l].node << ' ' << path[l].size << ' '
|
||||||
|
<< path[l].offset << '\n';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace IntervalMapImpl
|
} // namespace IntervalMapImpl
|
||||||
|
|
||||||
|
|
||||||
@ -1103,107 +1258,54 @@ class IntervalMap<KeyT, ValT, N, Traits>::const_iterator :
|
|||||||
public std::iterator<std::bidirectional_iterator_tag, ValT> {
|
public std::iterator<std::bidirectional_iterator_tag, ValT> {
|
||||||
protected:
|
protected:
|
||||||
friend class IntervalMap;
|
friend class IntervalMap;
|
||||||
typedef std::pair<IntervalMapImpl::NodeRef, unsigned> PathEntry;
|
|
||||||
typedef SmallVector<PathEntry, 4> Path;
|
|
||||||
|
|
||||||
// The map referred to.
|
// The map referred to.
|
||||||
IntervalMap *map;
|
IntervalMap *map;
|
||||||
|
|
||||||
// The offset into map's root node.
|
|
||||||
unsigned rootOffset;
|
|
||||||
|
|
||||||
// We store a full path from the root to the current position.
|
// We store a full path from the root to the current position.
|
||||||
//
|
|
||||||
// When rootOffset == map->rootSize, we are at end() and path() is empty.
|
|
||||||
// Otherwise, when branched these conditions hold:
|
|
||||||
//
|
|
||||||
// 1. path.front().first == rootBranch().subtree(rootOffset)
|
|
||||||
// 2. path[i].first == path[i-1].first.subtree(path[i-1].second)
|
|
||||||
// 3. path.size() == map->height.
|
|
||||||
//
|
|
||||||
// Thus, path.back() always refers to the current leaf node unless the root is
|
|
||||||
// unbranched.
|
|
||||||
//
|
|
||||||
// The path may be partially filled, but never between iterator calls.
|
// The path may be partially filled, but never between iterator calls.
|
||||||
Path path;
|
IntervalMapImpl::Path path;
|
||||||
|
|
||||||
explicit const_iterator(IntervalMap &map)
|
explicit const_iterator(IntervalMap &map) : map(&map) {}
|
||||||
: map(&map), rootOffset(map.rootSize) {}
|
|
||||||
|
|
||||||
bool branched() const {
|
bool branched() const {
|
||||||
assert(map && "Invalid iterator");
|
assert(map && "Invalid iterator");
|
||||||
return map->branched();
|
return map->branched();
|
||||||
}
|
}
|
||||||
|
|
||||||
IntervalMapImpl::NodeRef pathNode(unsigned h) const { return path[h].first; }
|
void setRoot(unsigned Offset) {
|
||||||
IntervalMapImpl::NodeRef &pathNode(unsigned h) { return path[h].first; }
|
if (branched())
|
||||||
unsigned pathOffset(unsigned h) const { return path[h].second; }
|
path.setRoot(&map->rootBranch(), map->rootSize, Offset);
|
||||||
unsigned &pathOffset(unsigned h) { return path[h].second; }
|
|
||||||
|
|
||||||
Leaf &treeLeaf() const {
|
|
||||||
assert(branched() && path.size() == map->height);
|
|
||||||
return path.back().first.template get<Leaf>();
|
|
||||||
}
|
|
||||||
unsigned treeLeafSize() const {
|
|
||||||
assert(branched() && path.size() == map->height);
|
|
||||||
return path.back().first.size();
|
|
||||||
}
|
|
||||||
unsigned &treeLeafOffset() {
|
|
||||||
assert(branched() && path.size() == map->height);
|
|
||||||
return path.back().second;
|
|
||||||
}
|
|
||||||
unsigned treeLeafOffset() const {
|
|
||||||
assert(branched() && path.size() == map->height);
|
|
||||||
return path.back().second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the next node ptr for an incomplete path.
|
|
||||||
IntervalMapImpl::NodeRef pathNextDown() {
|
|
||||||
assert(path.size() < map->height && "Path is already complete");
|
|
||||||
|
|
||||||
if (path.empty())
|
|
||||||
return map->rootBranch().subtree(rootOffset);
|
|
||||||
else
|
else
|
||||||
return path.back().first.subtree(path.back().second);
|
path.setRoot(&map->rootLeaf(), map->rootSize, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pathFillLeft();
|
|
||||||
void pathFillFind(KeyT x);
|
void pathFillFind(KeyT x);
|
||||||
void pathFillRight();
|
|
||||||
|
|
||||||
IntervalMapImpl::NodeRef leftSibling(unsigned level) const;
|
|
||||||
IntervalMapImpl::NodeRef rightSibling(unsigned level) const;
|
|
||||||
|
|
||||||
void treeIncrement();
|
|
||||||
void treeDecrement();
|
|
||||||
void treeFind(KeyT x);
|
void treeFind(KeyT x);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// valid - Return true if the current position is valid, false for end().
|
/// valid - Return true if the current position is valid, false for end().
|
||||||
bool valid() const {
|
bool valid() const { return path.valid(); }
|
||||||
assert(map && "Invalid iterator");
|
|
||||||
return rootOffset < map->rootSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// start - Return the beginning of the current interval.
|
/// start - Return the beginning of the current interval.
|
||||||
const KeyT &start() const {
|
const KeyT &start() const {
|
||||||
assert(valid() && "Cannot access invalid iterator");
|
assert(valid() && "Cannot access invalid iterator");
|
||||||
return branched() ? treeLeaf().start(treeLeafOffset()) :
|
return branched() ? path.leaf<Leaf>().start(path.leafOffset()) :
|
||||||
map->rootLeaf().start(rootOffset);
|
path.leaf<RootLeaf>().start(path.leafOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stop - Return the end of the current interval.
|
/// stop - Return the end of the current interval.
|
||||||
const KeyT &stop() const {
|
const KeyT &stop() const {
|
||||||
assert(valid() && "Cannot access invalid iterator");
|
assert(valid() && "Cannot access invalid iterator");
|
||||||
return branched() ? treeLeaf().stop(treeLeafOffset()) :
|
return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) :
|
||||||
map->rootLeaf().stop(rootOffset);
|
path.leaf<RootLeaf>().stop(path.leafOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// value - Return the mapped value at the current interval.
|
/// value - Return the mapped value at the current interval.
|
||||||
const ValT &value() const {
|
const ValT &value() const {
|
||||||
assert(valid() && "Cannot access invalid iterator");
|
assert(valid() && "Cannot access invalid iterator");
|
||||||
return branched() ? treeLeaf().value(treeLeafOffset()) :
|
return branched() ? path.leaf<Leaf>().value(path.leafOffset()) :
|
||||||
map->rootLeaf().value(rootOffset);
|
path.leaf<RootLeaf>().value(path.leafOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
const ValT &operator*() const {
|
const ValT &operator*() const {
|
||||||
@ -1212,8 +1314,11 @@ public:
|
|||||||
|
|
||||||
bool operator==(const const_iterator &RHS) const {
|
bool operator==(const const_iterator &RHS) const {
|
||||||
assert(map == RHS.map && "Cannot compare iterators from different maps");
|
assert(map == RHS.map && "Cannot compare iterators from different maps");
|
||||||
return rootOffset == RHS.rootOffset &&
|
if (!valid())
|
||||||
(!valid() || !branched() || path.back() == RHS.path.back());
|
return !RHS.valid();
|
||||||
|
if (path.leafOffset() != RHS.path.leafOffset())
|
||||||
|
return false;
|
||||||
|
return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const const_iterator &RHS) const {
|
bool operator!=(const const_iterator &RHS) const {
|
||||||
@ -1222,27 +1327,21 @@ public:
|
|||||||
|
|
||||||
/// goToBegin - Move to the first interval in map.
|
/// goToBegin - Move to the first interval in map.
|
||||||
void goToBegin() {
|
void goToBegin() {
|
||||||
rootOffset = 0;
|
setRoot(0);
|
||||||
path.clear();
|
|
||||||
if (branched())
|
if (branched())
|
||||||
pathFillLeft();
|
path.fillLeft(map->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// goToEnd - Move beyond the last interval in map.
|
/// goToEnd - Move beyond the last interval in map.
|
||||||
void goToEnd() {
|
void goToEnd() {
|
||||||
rootOffset = map->rootSize;
|
setRoot(map->rootSize);
|
||||||
path.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// preincrement - move to the next interval.
|
/// preincrement - move to the next interval.
|
||||||
const_iterator &operator++() {
|
const_iterator &operator++() {
|
||||||
assert(valid() && "Cannot increment end()");
|
assert(valid() && "Cannot increment end()");
|
||||||
if (!branched())
|
if (++path.leafOffset() == path.leafSize() && branched())
|
||||||
++rootOffset;
|
path.moveRight(map->height);
|
||||||
else if (treeLeafOffset() != treeLeafSize() - 1)
|
|
||||||
++treeLeafOffset();
|
|
||||||
else
|
|
||||||
treeIncrement();
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1255,13 +1354,10 @@ public:
|
|||||||
|
|
||||||
/// predecrement - move to the previous interval.
|
/// predecrement - move to the previous interval.
|
||||||
const_iterator &operator--() {
|
const_iterator &operator--() {
|
||||||
if (!branched()) {
|
if (path.leafOffset() && (valid() || !branched()))
|
||||||
assert(rootOffset && "Cannot decrement begin()");
|
--path.leafOffset();
|
||||||
--rootOffset;
|
|
||||||
} else if (valid() && treeLeafOffset())
|
|
||||||
--treeLeafOffset();
|
|
||||||
else
|
else
|
||||||
treeDecrement();
|
path.moveLeft(map->height);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,7 +1374,7 @@ public:
|
|||||||
if (branched())
|
if (branched())
|
||||||
treeFind(x);
|
treeFind(x);
|
||||||
else
|
else
|
||||||
rootOffset = map->rootLeaf().findFrom(0, map->rootSize, x);
|
setRoot(map->rootLeaf().findFrom(0, map->rootSize, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// advanceTo - Move to the first interval with stop >= x, or end().
|
/// advanceTo - Move to the first interval with stop >= x, or end().
|
||||||
@ -1288,150 +1384,30 @@ public:
|
|||||||
if (branched())
|
if (branched())
|
||||||
treeAdvanceTo(x);
|
treeAdvanceTo(x);
|
||||||
else
|
else
|
||||||
rootOffset = map->rootLeaf().findFrom(rootOffset, map->rootSize, x);
|
path.leafOffset() =
|
||||||
|
map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// pathFillLeft - Complete path by following left-most branches.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::pathFillLeft() {
|
|
||||||
IntervalMapImpl::NodeRef NR = pathNextDown();
|
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
|
||||||
path.push_back(PathEntry(NR, 0));
|
|
||||||
NR = NR.subtree(0);
|
|
||||||
}
|
|
||||||
path.push_back(PathEntry(NR, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// pathFillFind - Complete path by searching for x.
|
// pathFillFind - Complete path by searching for x.
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
void IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
const_iterator::pathFillFind(KeyT x) {
|
const_iterator::pathFillFind(KeyT x) {
|
||||||
IntervalMapImpl::NodeRef NR = pathNextDown();
|
IntervalMapImpl::NodeRef NR = path.subtree(path.height());
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
for (unsigned i = map->height - path.height() - 1; i; --i) {
|
||||||
unsigned p = NR.get<Branch>().safeFind(0, x);
|
unsigned p = NR.get<Branch>().safeFind(0, x);
|
||||||
path.push_back(PathEntry(NR, p));
|
path.push(NR, p);
|
||||||
NR = NR.subtree(p);
|
NR = NR.subtree(p);
|
||||||
}
|
}
|
||||||
path.push_back(PathEntry(NR, NR.get<Leaf>().safeFind(0, x)));
|
path.push(NR, NR.get<Leaf>().safeFind(0, x));
|
||||||
}
|
|
||||||
|
|
||||||
// pathFillRight - Complete path by adding rightmost entries.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::pathFillRight() {
|
|
||||||
IntervalMapImpl::NodeRef NR = pathNextDown();
|
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
|
||||||
unsigned p = NR.size() - 1;
|
|
||||||
path.push_back(PathEntry(NR, p));
|
|
||||||
NR = NR.subtree(p);
|
|
||||||
}
|
|
||||||
path.push_back(PathEntry(NR, NR.size() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// leftSibling - find the left sibling node to path[level].
|
|
||||||
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
|
||||||
/// @return The left sibling NodeRef, or NULL.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
IntervalMapImpl::NodeRef IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::leftSibling(unsigned level) const {
|
|
||||||
using namespace IntervalMapImpl;
|
|
||||||
assert(branched() && "Not at a branched node");
|
|
||||||
assert(level <= path.size() && "Bad level");
|
|
||||||
|
|
||||||
// Go up the tree until we can go left.
|
|
||||||
unsigned h = level;
|
|
||||||
while (h && pathOffset(h - 1) == 0)
|
|
||||||
--h;
|
|
||||||
|
|
||||||
// We are at the first leaf node, no left sibling.
|
|
||||||
if (!h && rootOffset == 0)
|
|
||||||
return NodeRef();
|
|
||||||
|
|
||||||
// NR is the subtree containing our left sibling.
|
|
||||||
NodeRef NR = h ?
|
|
||||||
pathNode(h - 1).subtree(pathOffset(h - 1) - 1) :
|
|
||||||
map->rootBranch().subtree(rootOffset - 1);
|
|
||||||
|
|
||||||
// Keep right all the way down.
|
|
||||||
for (; h != level; ++h)
|
|
||||||
NR = NR.subtree(NR.size() - 1);
|
|
||||||
return NR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// rightSibling - find the right sibling node to path[level].
|
|
||||||
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
|
||||||
/// @return The right sibling NodeRef, or NULL.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
IntervalMapImpl::NodeRef IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::rightSibling(unsigned level) const {
|
|
||||||
using namespace IntervalMapImpl;
|
|
||||||
assert(branched() && "Not at a branched node");
|
|
||||||
assert(level <= this->path.size() && "Bad level");
|
|
||||||
|
|
||||||
// Go up the tree until we can go right.
|
|
||||||
unsigned h = level;
|
|
||||||
while (h && pathOffset(h - 1) == pathNode(h - 1).size() - 1)
|
|
||||||
--h;
|
|
||||||
|
|
||||||
// We are at the last leaf node, no right sibling.
|
|
||||||
if (!h && rootOffset == map->rootSize - 1)
|
|
||||||
return NodeRef();
|
|
||||||
|
|
||||||
// NR is the subtree containing our right sibling.
|
|
||||||
NodeRef NR = h ?
|
|
||||||
pathNode(h - 1).subtree(pathOffset(h - 1) + 1) :
|
|
||||||
map->rootBranch().subtree(rootOffset + 1);
|
|
||||||
|
|
||||||
// Keep left all the way down.
|
|
||||||
for (; h != level; ++h)
|
|
||||||
NR = NR.subtree(0);
|
|
||||||
return NR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// treeIncrement - Move to the beginning of the next leaf node.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::treeIncrement() {
|
|
||||||
assert(branched() && "treeIncrement is not for small maps");
|
|
||||||
assert(path.size() == map->height && "inconsistent iterator");
|
|
||||||
do path.pop_back();
|
|
||||||
while (!path.empty() && path.back().second == path.back().first.size() - 1);
|
|
||||||
if (path.empty()) {
|
|
||||||
++rootOffset;
|
|
||||||
if (!valid())
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
++path.back().second;
|
|
||||||
pathFillLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
// treeDecrement - Move to the end of the previous leaf node.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::treeDecrement() {
|
|
||||||
assert(branched() && "treeDecrement is not for small maps");
|
|
||||||
if (valid()) {
|
|
||||||
assert(path.size() == map->height && "inconsistent iterator");
|
|
||||||
do path.pop_back();
|
|
||||||
while (!path.empty() && path.back().second == 0);
|
|
||||||
}
|
|
||||||
if (path.empty()) {
|
|
||||||
assert(rootOffset && "cannot treeDecrement() on begin()");
|
|
||||||
--rootOffset;
|
|
||||||
} else
|
|
||||||
--path.back().second;
|
|
||||||
pathFillRight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// treeFind - Find in a branched tree.
|
// treeFind - Find in a branched tree.
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
void IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
const_iterator::treeFind(KeyT x) {
|
const_iterator::treeFind(KeyT x) {
|
||||||
path.clear();
|
setRoot(map->rootBranch().findFrom(0, map->rootSize, x));
|
||||||
rootOffset = map->rootBranch().findFrom(0, map->rootSize, x);
|
|
||||||
if (valid())
|
if (valid())
|
||||||
pathFillFind(x);
|
pathFillFind(x);
|
||||||
}
|
}
|
||||||
@ -1488,7 +1464,6 @@ class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator {
|
|||||||
|
|
||||||
explicit iterator(IntervalMap &map) : const_iterator(map) {}
|
explicit iterator(IntervalMap &map) : const_iterator(map) {}
|
||||||
|
|
||||||
void setNodeSize(unsigned Level, unsigned Size);
|
|
||||||
void setNodeStop(unsigned Level, KeyT Stop);
|
void setNodeStop(unsigned Level, KeyT Stop);
|
||||||
bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
|
bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
|
||||||
template <typename NodeT> bool overflow(unsigned Level);
|
template <typename NodeT> bool overflow(unsigned Level);
|
||||||
@ -1500,31 +1475,22 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// setNodeSize - Set the size of the node at path[level], updating both path
|
|
||||||
/// and the real tree.
|
|
||||||
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
|
||||||
/// @param size New node size.
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
iterator::setNodeSize(unsigned Level, unsigned Size) {
|
|
||||||
this->pathNode(Level).setSize(Size);
|
|
||||||
if (Level)
|
|
||||||
this->pathNode(Level-1).subtree(this->pathOffset(Level-1)).setSize(Size);
|
|
||||||
else
|
|
||||||
this->map->rootBranch().subtree(this->rootOffset).setSize(Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// setNodeStop - Update the stop key of the current node at level and above.
|
/// setNodeStop - Update the stop key of the current node at level and above.
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
void IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
iterator::setNodeStop(unsigned Level, KeyT Stop) {
|
iterator::setNodeStop(unsigned Level, KeyT Stop) {
|
||||||
while (Level--) {
|
// There are no references to the root node, so nothing to update.
|
||||||
this->pathNode(Level).template get<Branch>()
|
if (!Level)
|
||||||
.stop(this->pathOffset(Level)) = Stop;
|
return;
|
||||||
if (this->pathOffset(Level) != this->pathNode(Level).size() - 1)
|
IntervalMapImpl::Path &P = this->path;
|
||||||
|
// Update nodes pointing to the current node.
|
||||||
|
while (--Level) {
|
||||||
|
P.node<Branch>(Level).stop(P.offset(Level)) = Stop;
|
||||||
|
if (!P.atLastBranch(Level))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->map->rootBranch().stop(this->rootOffset) = Stop;
|
// Update root separately since it has a different layout.
|
||||||
|
P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// insertNode - insert a node before the current path at level.
|
/// insertNode - insert a node before the current path at level.
|
||||||
@ -1536,42 +1502,40 @@ iterator::setNodeStop(unsigned Level, KeyT Stop) {
|
|||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
bool IntervalMap<KeyT, ValT, N, Traits>::
|
bool IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
|
iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
|
||||||
|
assert(Level && "Cannot insert next to the root");
|
||||||
bool SplitRoot = false;
|
bool SplitRoot = false;
|
||||||
|
IntervalMap &IM = *this->map;
|
||||||
|
IntervalMapImpl::Path &P = this->path;
|
||||||
|
|
||||||
if (!Level) {
|
if (Level == 1) {
|
||||||
// Insert into the root branch node.
|
// Insert into the root branch node.
|
||||||
IntervalMap &IM = *this->map;
|
|
||||||
if (IM.rootSize < RootBranch::Capacity) {
|
if (IM.rootSize < RootBranch::Capacity) {
|
||||||
IM.rootBranch().insert(this->rootOffset, IM.rootSize, Node, Stop);
|
IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop);
|
||||||
++IM.rootSize;
|
P.setSize(0, ++IM.rootSize);
|
||||||
return SplitRoot;
|
return SplitRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to split the root while keeping our position.
|
// We need to split the root while keeping our position.
|
||||||
SplitRoot = true;
|
SplitRoot = true;
|
||||||
IdxPair Offset = IM.splitRoot(this->rootOffset);
|
IdxPair Offset = IM.splitRoot(P.offset(0));
|
||||||
this->rootOffset = Offset.first;
|
P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
|
||||||
this->path.insert(this->path.begin(),std::make_pair(
|
|
||||||
this->map->rootBranch().subtree(Offset.first), Offset.second));
|
// Fall through to insert at the new higher level.
|
||||||
Level = 1;
|
++Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When inserting before end(), make sure we have a valid path.
|
// When inserting before end(), make sure we have a valid path.
|
||||||
if (!this->valid()) {
|
P.legalizeForInsert(--Level);
|
||||||
this->treeDecrement();
|
|
||||||
++this->pathOffset(Level-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert into the branch node at level-1.
|
// Insert into the branch node at Level-1.
|
||||||
if (this->pathNode(Level-1).size() == Branch::Capacity) {
|
if (P.size(Level) == Branch::Capacity) {
|
||||||
|
// Branch node is full, handle handle the overflow.
|
||||||
assert(!SplitRoot && "Cannot overflow after splitting the root");
|
assert(!SplitRoot && "Cannot overflow after splitting the root");
|
||||||
SplitRoot = overflow<Branch>(Level - 1);
|
SplitRoot = overflow<Branch>(Level);
|
||||||
Level += SplitRoot;
|
Level += SplitRoot;
|
||||||
}
|
}
|
||||||
IntervalMapImpl::NodeRef NR = this->pathNode(Level-1);
|
P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop);
|
||||||
unsigned Offset = this->pathOffset(Level-1);
|
P.setSize(Level, P.size(Level) + 1);
|
||||||
NR.get<Branch>().insert(Offset, NR.size(), Node, Stop);
|
|
||||||
setNodeSize(Level - 1, NR.size() + 1);
|
|
||||||
return SplitRoot;
|
return SplitRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1581,18 +1545,24 @@ void IntervalMap<KeyT, ValT, N, Traits>::
|
|||||||
iterator::insert(KeyT a, KeyT b, ValT y) {
|
iterator::insert(KeyT a, KeyT b, ValT y) {
|
||||||
if (this->branched())
|
if (this->branched())
|
||||||
return treeInsert(a, b, y);
|
return treeInsert(a, b, y);
|
||||||
IdxPair IP = this->map->rootLeaf().insertFrom(this->rootOffset,
|
IntervalMap &IM = *this->map;
|
||||||
this->map->rootSize,
|
IntervalMapImpl::Path &P = this->path;
|
||||||
a, b, y);
|
|
||||||
|
// Try simple root leaf insert.
|
||||||
|
IdxPair IP = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y);
|
||||||
|
|
||||||
|
// Was the root node insert successful?
|
||||||
if (IP.second <= RootLeaf::Capacity) {
|
if (IP.second <= RootLeaf::Capacity) {
|
||||||
this->rootOffset = IP.first;
|
P.leafOffset() = IP.first;
|
||||||
this->map->rootSize = IP.second;
|
P.setSize(0, IM.rootSize = IP.second);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IdxPair Offset = this->map->branchRoot(this->rootOffset);
|
|
||||||
this->rootOffset = Offset.first;
|
// Root leaf node is full, we must branch.
|
||||||
this->path.push_back(std::make_pair(
|
IdxPair Offset = IM.branchRoot(P.leafOffset());
|
||||||
this->map->rootBranch().subtree(Offset.first), Offset.second));
|
P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
|
||||||
|
|
||||||
|
// Now it fits in the new leaf.
|
||||||
treeInsert(a, b, y);
|
treeInsert(a, b, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1600,29 +1570,26 @@ iterator::insert(KeyT a, KeyT b, ValT y) {
|
|||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
void IntervalMap<KeyT, ValT, N, Traits>::
|
void IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
iterator::treeInsert(KeyT a, KeyT b, ValT y) {
|
iterator::treeInsert(KeyT a, KeyT b, ValT y) {
|
||||||
if (!this->valid()) {
|
IntervalMap &IM = *this->map;
|
||||||
// end() has an empty path. Go back to the last leaf node and use an
|
IntervalMapImpl::Path &P = this->path;
|
||||||
// invalid offset instead.
|
|
||||||
this->treeDecrement();
|
P.legalizeForInsert(IM.height);
|
||||||
++this->treeLeafOffset();
|
IdxPair IP = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
|
||||||
|
|
||||||
|
// Leaf insertion unsuccessful? Overflow and try again.
|
||||||
|
if (IP.second > Leaf::Capacity) {
|
||||||
|
overflow<Leaf>(IM.height);
|
||||||
|
IP = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
|
||||||
|
assert(IP.second <= Leaf::Capacity && "overflow() didn't make room");
|
||||||
}
|
}
|
||||||
IdxPair IP = this->treeLeaf().insertFrom(this->treeLeafOffset(),
|
|
||||||
this->treeLeafSize(), a, b, y);
|
// Inserted, update offset and leaf size.
|
||||||
this->treeLeafOffset() = IP.first;
|
P.leafOffset() = IP.first;
|
||||||
if (IP.second <= Leaf::Capacity) {
|
P.setSize(IM.height, IP.second);
|
||||||
setNodeSize(this->map->height - 1, IP.second);
|
|
||||||
if (IP.first == IP.second - 1)
|
// Insert was the last node entry, update stops.
|
||||||
setNodeStop(this->map->height - 1, this->treeLeaf().stop(IP.first));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Leaf node has no space.
|
|
||||||
overflow<Leaf>(this->map->height - 1);
|
|
||||||
IP = this->treeLeaf().insertFrom(this->treeLeafOffset(),
|
|
||||||
this->treeLeafSize(), a, b, y);
|
|
||||||
this->treeLeafOffset() = IP.first;
|
|
||||||
setNodeSize(this->map->height-1, IP.second);
|
|
||||||
if (IP.first == IP.second - 1)
|
if (IP.first == IP.second - 1)
|
||||||
setNodeStop(this->map->height - 1, this->treeLeaf().stop(IP.first));
|
setNodeStop(IM.height, P.leaf<Leaf>().stop(IP.first));
|
||||||
|
|
||||||
// FIXME: Handle cross-node coalescing.
|
// FIXME: Handle cross-node coalescing.
|
||||||
}
|
}
|
||||||
@ -1638,26 +1605,26 @@ template <typename NodeT>
|
|||||||
bool IntervalMap<KeyT, ValT, N, Traits>::
|
bool IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
iterator::overflow(unsigned Level) {
|
iterator::overflow(unsigned Level) {
|
||||||
using namespace IntervalMapImpl;
|
using namespace IntervalMapImpl;
|
||||||
|
Path &P = this->path;
|
||||||
unsigned CurSize[4];
|
unsigned CurSize[4];
|
||||||
NodeT *Node[4];
|
NodeT *Node[4];
|
||||||
unsigned Nodes = 0;
|
unsigned Nodes = 0;
|
||||||
unsigned Elements = 0;
|
unsigned Elements = 0;
|
||||||
unsigned Offset = this->pathOffset(Level);
|
unsigned Offset = P.offset(Level);
|
||||||
|
|
||||||
// Do we have a left sibling?
|
// Do we have a left sibling?
|
||||||
NodeRef LeftSib = this->leftSibling(Level);
|
NodeRef LeftSib = P.getLeftSibling(Level);
|
||||||
if (LeftSib) {
|
if (LeftSib) {
|
||||||
Offset += Elements = CurSize[Nodes] = LeftSib.size();
|
Offset += Elements = CurSize[Nodes] = LeftSib.size();
|
||||||
Node[Nodes++] = &LeftSib.get<NodeT>();
|
Node[Nodes++] = &LeftSib.get<NodeT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current node.
|
// Current node.
|
||||||
NodeRef CurNode = this->pathNode(Level);
|
Elements += CurSize[Nodes] = P.size(Level);
|
||||||
Elements += CurSize[Nodes] = CurNode.size();
|
Node[Nodes++] = &P.node<NodeT>(Level);
|
||||||
Node[Nodes++] = &CurNode.get<NodeT>();
|
|
||||||
|
|
||||||
// Do we have a right sibling?
|
// Do we have a right sibling?
|
||||||
NodeRef RightSib = this->rightSibling(Level);
|
NodeRef RightSib = P.getRightSibling(Level);
|
||||||
if (RightSib) {
|
if (RightSib) {
|
||||||
Offset += Elements = CurSize[Nodes] = RightSib.size();
|
Offset += Elements = CurSize[Nodes] = RightSib.size();
|
||||||
Node[Nodes++] = &RightSib.get<NodeT>();
|
Node[Nodes++] = &RightSib.get<NodeT>();
|
||||||
@ -1682,7 +1649,7 @@ iterator::overflow(unsigned Level) {
|
|||||||
|
|
||||||
// Move current location to the leftmost node.
|
// Move current location to the leftmost node.
|
||||||
if (LeftSib)
|
if (LeftSib)
|
||||||
this->treeDecrement();
|
P.moveLeft(Level);
|
||||||
|
|
||||||
// Move elements right.
|
// Move elements right.
|
||||||
for (int n = Nodes - 1; n; --n) {
|
for (int n = Nodes - 1; n; --n) {
|
||||||
@ -1728,21 +1695,21 @@ iterator::overflow(unsigned Level) {
|
|||||||
SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
|
SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
|
||||||
Level += SplitRoot;
|
Level += SplitRoot;
|
||||||
} else {
|
} else {
|
||||||
setNodeSize(Level, NewSize[Pos]);
|
P.setSize(Level, NewSize[Pos]);
|
||||||
setNodeStop(Level, Stop);
|
setNodeStop(Level, Stop);
|
||||||
}
|
}
|
||||||
if (Pos + 1 == Nodes)
|
if (Pos + 1 == Nodes)
|
||||||
break;
|
break;
|
||||||
this->treeIncrement();
|
P.moveRight(Level);
|
||||||
++Pos;
|
++Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where was I? Find NewOffset.
|
// Where was I? Find NewOffset.
|
||||||
while(Pos != NewOffset.first) {
|
while(Pos != NewOffset.first) {
|
||||||
this->treeDecrement();
|
P.moveLeft(Level);
|
||||||
--Pos;
|
--Pos;
|
||||||
}
|
}
|
||||||
this->pathOffset(Level) = NewOffset.second;
|
P.offset(Level) = NewOffset.second;
|
||||||
return SplitRoot;
|
return SplitRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,107 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace IntervalMapImpl {
|
namespace IntervalMapImpl {
|
||||||
|
|
||||||
|
void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
|
||||||
|
assert(!path.empty() && "Can't replace missing root");
|
||||||
|
path.front() = Entry(Root, Size, Offsets.first);
|
||||||
|
path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRef Path::getLeftSibling(unsigned Level) const {
|
||||||
|
// The root has no siblings.
|
||||||
|
if (Level == 0)
|
||||||
|
return NodeRef();
|
||||||
|
|
||||||
|
// Go up the tree until we can go left.
|
||||||
|
unsigned l = Level - 1;
|
||||||
|
while (l && path[l].offset == 0)
|
||||||
|
--l;
|
||||||
|
|
||||||
|
// We can't go left.
|
||||||
|
if (path[l].offset == 0)
|
||||||
|
return NodeRef();
|
||||||
|
|
||||||
|
// NR is the subtree containing our left sibling.
|
||||||
|
NodeRef NR = path[l].subtree(path[l].offset - 1);
|
||||||
|
|
||||||
|
// Keep right all the way down.
|
||||||
|
for (++l; l != Level; ++l)
|
||||||
|
NR = NR.subtree(NR.size() - 1);
|
||||||
|
return NR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Path::moveLeft(unsigned Level) {
|
||||||
|
assert(Level != 0 && "Cannot move the root node");
|
||||||
|
|
||||||
|
// Go up the tree until we can go left.
|
||||||
|
unsigned l = 0;
|
||||||
|
if (valid()) {
|
||||||
|
l = Level - 1;
|
||||||
|
while (path[l].offset == 0) {
|
||||||
|
assert(l != 0 && "Cannot move beyond begin()");
|
||||||
|
--l;
|
||||||
|
}
|
||||||
|
} else if (height() < Level)
|
||||||
|
// end() may have created a height=0 path.
|
||||||
|
path.resize(Level + 1, Entry(0, 0, 0));
|
||||||
|
|
||||||
|
// NR is the subtree containing our left sibling.
|
||||||
|
--path[l].offset;
|
||||||
|
NodeRef NR = subtree(l);
|
||||||
|
|
||||||
|
// Get the rightmost node in the subtree.
|
||||||
|
for (++l; l != Level; ++l) {
|
||||||
|
path[l] = Entry(NR, NR.size() - 1);
|
||||||
|
NR = NR.subtree(NR.size() - 1);
|
||||||
|
}
|
||||||
|
path[l] = Entry(NR, NR.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRef Path::getRightSibling(unsigned Level) const {
|
||||||
|
// The root has no siblings.
|
||||||
|
if (Level == 0)
|
||||||
|
return NodeRef();
|
||||||
|
|
||||||
|
// Go up the tree until we can go right.
|
||||||
|
unsigned l = Level - 1;
|
||||||
|
while (l && atLastBranch(l))
|
||||||
|
--l;
|
||||||
|
|
||||||
|
// We can't go right.
|
||||||
|
if (atLastBranch(l))
|
||||||
|
return NodeRef();
|
||||||
|
|
||||||
|
// NR is the subtree containing our right sibling.
|
||||||
|
NodeRef NR = path[l].subtree(path[l].offset + 1);
|
||||||
|
|
||||||
|
// Keep left all the way down.
|
||||||
|
for (++l; l != Level; ++l)
|
||||||
|
NR = NR.subtree(0);
|
||||||
|
return NR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Path::moveRight(unsigned Level) {
|
||||||
|
assert(Level != 0 && "Cannot move the root node");
|
||||||
|
|
||||||
|
// Go up the tree until we can go right.
|
||||||
|
unsigned l = Level - 1;
|
||||||
|
while (l && atLastBranch(l))
|
||||||
|
--l;
|
||||||
|
|
||||||
|
// NR is the subtree containing our right sibling. If we hit end(), we have
|
||||||
|
// offset(0) == node(0).size().
|
||||||
|
if (++path[l].offset == path[l].size)
|
||||||
|
return;
|
||||||
|
NodeRef NR = subtree(l);
|
||||||
|
|
||||||
|
for (++l; l != Level; ++l) {
|
||||||
|
path[l] = Entry(NR, 0);
|
||||||
|
NR = NR.subtree(0);
|
||||||
|
}
|
||||||
|
path[l] = Entry(NR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
|
IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
|
||||||
const unsigned *CurSize, unsigned NewSize[],
|
const unsigned *CurSize, unsigned NewSize[],
|
||||||
unsigned Position, bool Grow) {
|
unsigned Position, bool Grow) {
|
||||||
@ -56,5 +157,5 @@ IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace IntervalMapImpl
|
} // namespace IntervalMapImpl
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user