mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-09 05:47:13 +00:00
Detemplatize NodeRef.
It is now possible to navigate the B+-tree using NodeRef::subtree() and NodeRef::size() without knowing the key and value template types used in the tree. llvm-svn: 119880
This commit is contained in:
parent
4a44e92fd1
commit
de3ebc098a
@ -378,14 +378,7 @@ struct CacheAlignedPointerTraits {
|
|||||||
enum { NumLowBitsAvailable = Log2CacheLine };
|
enum { NumLowBitsAvailable = Log2CacheLine };
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename KeyT, typename ValT, typename Traits>
|
|
||||||
class NodeRef {
|
class NodeRef {
|
||||||
public:
|
|
||||||
typedef LeafNode<KeyT, ValT, NodeSizer<KeyT, ValT>::LeafSize, Traits> Leaf;
|
|
||||||
typedef BranchNode<KeyT, ValT, NodeSizer<KeyT, ValT>::BranchSize,
|
|
||||||
Traits> Branch;
|
|
||||||
|
|
||||||
private:
|
|
||||||
PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip;
|
PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -395,11 +388,11 @@ public:
|
|||||||
/// operator bool - Detect a null ref.
|
/// operator bool - Detect a null ref.
|
||||||
operator bool() const { return pip.getOpaqueValue(); }
|
operator bool() const { return pip.getOpaqueValue(); }
|
||||||
|
|
||||||
/// NodeRef - Create a reference to the leaf node p with n elements.
|
/// NodeRef - Create a reference to the node p with n elements.
|
||||||
NodeRef(Leaf *p, unsigned n) : pip(p, n - 1) {}
|
template <typename NodeT>
|
||||||
|
NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) {
|
||||||
/// NodeRef - Create a reference to the branch node p with n elements.
|
assert(n <= NodeT::Capacity && "Size too big for node");
|
||||||
NodeRef(Branch *p, unsigned n) : pip(p, n - 1) {}
|
}
|
||||||
|
|
||||||
/// size - Return the number of elements in the referenced node.
|
/// size - Return the number of elements in the referenced node.
|
||||||
unsigned size() const { return pip.getInt() + 1; }
|
unsigned size() const { return pip.getInt() + 1; }
|
||||||
@ -407,16 +400,17 @@ public:
|
|||||||
/// setSize - Update the node size.
|
/// setSize - Update the node size.
|
||||||
void setSize(unsigned n) { pip.setInt(n - 1); }
|
void setSize(unsigned n) { pip.setInt(n - 1); }
|
||||||
|
|
||||||
/// leaf - Return the referenced leaf node.
|
/// subtree - Access the i'th subtree reference in a branch node.
|
||||||
/// Note there are no dynamic type checks.
|
/// This depends on branch nodes storing the NodeRef array as their first
|
||||||
Leaf &leaf() const {
|
/// member.
|
||||||
return *reinterpret_cast<Leaf*>(pip.getPointer());
|
NodeRef &subtree(unsigned i) {
|
||||||
|
return reinterpret_cast<NodeRef*>(pip.getPointer())[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// branch - Return the referenced branch node.
|
/// get - Dereference as a NodeT reference.
|
||||||
/// Note there are no dynamic type checks.
|
template <typename NodeT>
|
||||||
Branch &branch() const {
|
NodeT &get() const {
|
||||||
return *reinterpret_cast<Branch*>(pip.getPointer());
|
return *reinterpret_cast<NodeT*>(pip.getPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const NodeRef &RHS) const {
|
bool operator==(const NodeRef &RHS) const {
|
||||||
@ -442,12 +436,12 @@ public:
|
|||||||
//
|
//
|
||||||
// These constraints are always satisfied:
|
// These constraints are always satisfied:
|
||||||
//
|
//
|
||||||
// - Traits::stopLess(key[i].start, key[i].stop) - Non-empty, sane intervals.
|
// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals.
|
||||||
//
|
//
|
||||||
// - Traits::stopLess(key[i].stop, key[i + 1].start) - Sorted.
|
// - Traits::stopLess(stop(i), start(i + 1) - Sorted.
|
||||||
//
|
//
|
||||||
// - val[i] != val[i + 1] ||
|
// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1))
|
||||||
// !Traits::adjacent(key[i].stop, key[i + 1].start) - Fully coalesced.
|
// - Fully coalesced.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -634,14 +628,13 @@ extendStop(unsigned i, unsigned Size, KeyT b) {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
class BranchNode : public NodeBase<NodeRef<KeyT, ValT, Traits>, KeyT, N> {
|
class BranchNode : public NodeBase<NodeRef, KeyT, N> {
|
||||||
typedef NodeRef<KeyT, ValT, Traits> NodeRefT;
|
|
||||||
public:
|
public:
|
||||||
const KeyT &stop(unsigned i) const { return this->second[i]; }
|
const KeyT &stop(unsigned i) const { return this->second[i]; }
|
||||||
const NodeRefT &subtree(unsigned i) const { return this->first[i]; }
|
const NodeRef &subtree(unsigned i) const { return this->first[i]; }
|
||||||
|
|
||||||
KeyT &stop(unsigned i) { return this->second[i]; }
|
KeyT &stop(unsigned i) { return this->second[i]; }
|
||||||
NodeRefT &subtree(unsigned i) { return this->first[i]; }
|
NodeRef &subtree(unsigned i) { return this->first[i]; }
|
||||||
|
|
||||||
/// findFrom - Find the first subtree after i that may contain x.
|
/// findFrom - Find the first subtree after i that may contain x.
|
||||||
/// @param i Starting index for the search.
|
/// @param i Starting index for the search.
|
||||||
@ -675,7 +668,7 @@ public:
|
|||||||
/// safeLookup - Get the subtree containing x, Assuming that x is in range.
|
/// safeLookup - Get the subtree containing x, Assuming that x is in range.
|
||||||
/// @param x Key to search for.
|
/// @param x Key to search for.
|
||||||
/// @return Subtree containing x
|
/// @return Subtree containing x
|
||||||
NodeRefT safeLookup(KeyT x) const {
|
NodeRef safeLookup(KeyT x) const {
|
||||||
return subtree(safeFind(0, x));
|
return subtree(safeFind(0, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,7 +677,7 @@ public:
|
|||||||
/// @param Size Number of elements in node.
|
/// @param Size Number of elements in node.
|
||||||
/// @param Node Subtree to insert.
|
/// @param Node Subtree to insert.
|
||||||
/// @param Stop Last key in subtree.
|
/// @param Stop Last key in subtree.
|
||||||
void insert(unsigned i, unsigned Size, NodeRefT Node, KeyT Stop) {
|
void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) {
|
||||||
assert(Size < N && "branch node overflow");
|
assert(Size < N && "branch node overflow");
|
||||||
assert(i <= Size && "Bad insert position");
|
assert(i <= Size && "Bad insert position");
|
||||||
this->shift(i, Size);
|
this->shift(i, Size);
|
||||||
@ -700,7 +693,7 @@ public:
|
|||||||
errs() << "\"];\n";
|
errs() << "\"];\n";
|
||||||
for (unsigned i = 0; i != Size; ++i)
|
for (unsigned i = 0; i != Size; ++i)
|
||||||
errs() << " N" << this << ":s" << i << " -> N"
|
errs() << " N" << this << ":s" << i << " -> N"
|
||||||
<< &subtree(i).branch() << ";\n";
|
<< &subtree(i).template get<BranchNode>() << ";\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -717,10 +710,10 @@ template <typename KeyT, typename ValT,
|
|||||||
unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
|
unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
|
||||||
typename Traits = IntervalMapInfo<KeyT> >
|
typename Traits = IntervalMapInfo<KeyT> >
|
||||||
class IntervalMap {
|
class IntervalMap {
|
||||||
typedef IntervalMapImpl::NodeRef<KeyT, ValT, Traits> NodeRef;
|
typedef IntervalMapImpl::NodeSizer<KeyT, ValT> Sizer;
|
||||||
typedef IntervalMapImpl::NodeSizer<KeyT, ValT> NodeSizer;
|
typedef IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits> Leaf;
|
||||||
typedef typename NodeRef::Leaf Leaf;
|
typedef IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits>
|
||||||
typedef typename NodeRef::Branch Branch;
|
Branch;
|
||||||
typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf;
|
typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf;
|
||||||
typedef IntervalMapImpl::IdxPair IdxPair;
|
typedef IntervalMapImpl::IdxPair IdxPair;
|
||||||
|
|
||||||
@ -728,11 +721,12 @@ class IntervalMap {
|
|||||||
// corresponding RootBranch capacity.
|
// corresponding RootBranch capacity.
|
||||||
enum {
|
enum {
|
||||||
DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) /
|
DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) /
|
||||||
(sizeof(KeyT) + sizeof(NodeRef)),
|
(sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)),
|
||||||
RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1
|
RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits> RootBranch;
|
typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits>
|
||||||
|
RootBranch;
|
||||||
|
|
||||||
// When branched, we store a global start key as well as the branch node.
|
// When branched, we store a global start key as well as the branch node.
|
||||||
struct RootBranchData {
|
struct RootBranchData {
|
||||||
@ -746,7 +740,7 @@ class IntervalMap {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename NodeSizer::Allocator Allocator;
|
typedef typename Sizer::Allocator Allocator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The root data is either a RootLeaf or a RootBranchData instance.
|
// The root data is either a RootLeaf or a RootBranchData instance.
|
||||||
@ -837,8 +831,9 @@ private:
|
|||||||
bool branched() const { return height > 0; }
|
bool branched() const { return height > 0; }
|
||||||
|
|
||||||
ValT treeSafeLookup(KeyT x, ValT NotFound) const;
|
ValT treeSafeLookup(KeyT x, ValT NotFound) const;
|
||||||
void visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Level));
|
void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef,
|
||||||
void deleteNode(NodeRef Node, unsigned Level);
|
unsigned Level));
|
||||||
|
void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
|
explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
|
||||||
@ -933,7 +928,7 @@ public:
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void dump();
|
void dump();
|
||||||
void dumpNode(NodeRef Node, unsigned Height);
|
void dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -944,10 +939,10 @@ ValT IntervalMap<KeyT, ValT, N, Traits>::
|
|||||||
treeSafeLookup(KeyT x, ValT NotFound) const {
|
treeSafeLookup(KeyT x, ValT NotFound) const {
|
||||||
assert(branched() && "treeLookup assumes a branched root");
|
assert(branched() && "treeLookup assumes a branched root");
|
||||||
|
|
||||||
NodeRef NR = rootBranch().safeLookup(x);
|
IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x);
|
||||||
for (unsigned h = height-1; h; --h)
|
for (unsigned h = height-1; h; --h)
|
||||||
NR = NR.branch().safeLookup(x);
|
NR = NR.get<Branch>().safeLookup(x);
|
||||||
return NR.leaf().safeLookup(x, NotFound);
|
return NR.get<Leaf>().safeLookup(x, NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -956,6 +951,7 @@ treeSafeLookup(KeyT x, ValT NotFound) const {
|
|||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
|
IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
branchRoot(unsigned Position) {
|
branchRoot(unsigned Position) {
|
||||||
|
using namespace IntervalMapImpl;
|
||||||
// How many external leaf nodes to hold RootLeaf+1?
|
// How many external leaf nodes to hold RootLeaf+1?
|
||||||
const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1;
|
const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1;
|
||||||
|
|
||||||
@ -975,17 +971,17 @@ branchRoot(unsigned Position) {
|
|||||||
NodeRef node[Nodes];
|
NodeRef node[Nodes];
|
||||||
for (unsigned n = 0; n != Nodes; ++n) {
|
for (unsigned n = 0; n != Nodes; ++n) {
|
||||||
node[n] = NodeRef(allocLeaf(), size[n]);
|
node[n] = NodeRef(allocLeaf(), size[n]);
|
||||||
node[n].leaf().copy(rootLeaf(), pos, 0, size[n]);
|
node[n].template get<Leaf>().copy(rootLeaf(), pos, 0, size[n]);
|
||||||
pos += size[n];
|
pos += size[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the old leaf node, construct branch node instead.
|
// Destroy the old leaf node, construct branch node instead.
|
||||||
switchRootToBranch();
|
switchRootToBranch();
|
||||||
for (unsigned n = 0; n != Nodes; ++n) {
|
for (unsigned n = 0; n != Nodes; ++n) {
|
||||||
rootBranch().stop(n) = node[n].leaf().stop(size[n]-1);
|
rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1);
|
||||||
rootBranch().subtree(n) = node[n];
|
rootBranch().subtree(n) = node[n];
|
||||||
}
|
}
|
||||||
rootBranchStart() = node[0].leaf().start(0);
|
rootBranchStart() = node[0].template get<Leaf>().start(0);
|
||||||
rootSize = Nodes;
|
rootSize = Nodes;
|
||||||
return NewOffset;
|
return NewOffset;
|
||||||
}
|
}
|
||||||
@ -995,6 +991,7 @@ branchRoot(unsigned Position) {
|
|||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
|
IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
splitRoot(unsigned Position) {
|
splitRoot(unsigned Position) {
|
||||||
|
using namespace IntervalMapImpl;
|
||||||
// How many external leaf nodes to hold RootBranch+1?
|
// How many external leaf nodes to hold RootBranch+1?
|
||||||
const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1;
|
const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1;
|
||||||
|
|
||||||
@ -1014,12 +1011,12 @@ splitRoot(unsigned Position) {
|
|||||||
NodeRef Node[Nodes];
|
NodeRef Node[Nodes];
|
||||||
for (unsigned n = 0; n != Nodes; ++n) {
|
for (unsigned n = 0; n != Nodes; ++n) {
|
||||||
Node[n] = NodeRef(allocBranch(), Size[n]);
|
Node[n] = NodeRef(allocBranch(), Size[n]);
|
||||||
Node[n].branch().copy(rootBranch(), Pos, 0, Size[n]);
|
Node[n].template get<Branch>().copy(rootBranch(), Pos, 0, Size[n]);
|
||||||
Pos += Size[n];
|
Pos += Size[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned n = 0; n != Nodes; ++n) {
|
for (unsigned n = 0; n != Nodes; ++n) {
|
||||||
rootBranch().stop(n) = Node[n].branch().stop(Size[n]-1);
|
rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1);
|
||||||
rootBranch().subtree(n) = Node[n];
|
rootBranch().subtree(n) = Node[n];
|
||||||
}
|
}
|
||||||
rootSize = Nodes;
|
rootSize = Nodes;
|
||||||
@ -1029,10 +1026,10 @@ splitRoot(unsigned Position) {
|
|||||||
/// visitNodes - Visit each external node.
|
/// visitNodes - Visit each external node.
|
||||||
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>::
|
||||||
visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Height)) {
|
visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) {
|
||||||
if (!branched())
|
if (!branched())
|
||||||
return;
|
return;
|
||||||
SmallVector<NodeRef, 4> Refs, NextRefs;
|
SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs;
|
||||||
|
|
||||||
// Collect level 0 nodes from the root.
|
// Collect level 0 nodes from the root.
|
||||||
for (unsigned i = 0; i != rootSize; ++i)
|
for (unsigned i = 0; i != rootSize; ++i)
|
||||||
@ -1041,9 +1038,8 @@ visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Height)) {
|
|||||||
// Visit all branch nodes.
|
// Visit all branch nodes.
|
||||||
for (unsigned h = height - 1; h; --h) {
|
for (unsigned h = height - 1; h; --h) {
|
||||||
for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
|
||||||
Branch &B = Refs[i].branch();
|
|
||||||
for (unsigned j = 0, s = Refs[i].size(); j != s; ++j)
|
for (unsigned j = 0, s = Refs[i].size(); j != s; ++j)
|
||||||
NextRefs.push_back(B.subtree(j));
|
NextRefs.push_back(Refs[i].subtree(j));
|
||||||
(this->*f)(Refs[i], h);
|
(this->*f)(Refs[i], h);
|
||||||
}
|
}
|
||||||
Refs.clear();
|
Refs.clear();
|
||||||
@ -1057,11 +1053,11 @@ visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Height)) {
|
|||||||
|
|
||||||
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>::
|
||||||
deleteNode(NodeRef Node, unsigned Level) {
|
deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) {
|
||||||
if (Level)
|
if (Level)
|
||||||
deleteBranch(&Node.branch());
|
deleteBranch(&Node.get<Branch>());
|
||||||
else
|
else
|
||||||
deleteLeaf(&Node.leaf());
|
deleteLeaf(&Node.get<Leaf>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
@ -1077,11 +1073,11 @@ clear() {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
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>::
|
||||||
dumpNode(NodeRef Node, unsigned Height) {
|
dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height) {
|
||||||
if (Height)
|
if (Height)
|
||||||
Node.branch().dump(Node.size());
|
Node.get<Branch>().dump(Node.size());
|
||||||
else
|
else
|
||||||
Node.leaf().dump(Node.size());
|
Node.get<Leaf>().dump(Node.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
@ -1106,7 +1102,7 @@ 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<NodeRef, unsigned> PathEntry;
|
typedef std::pair<IntervalMapImpl::NodeRef, unsigned> PathEntry;
|
||||||
typedef SmallVector<PathEntry, 4> Path;
|
typedef SmallVector<PathEntry, 4> Path;
|
||||||
|
|
||||||
// The map referred to.
|
// The map referred to.
|
||||||
@ -1121,7 +1117,7 @@ protected:
|
|||||||
// Otherwise, when branched these conditions hold:
|
// Otherwise, when branched these conditions hold:
|
||||||
//
|
//
|
||||||
// 1. path.front().first == rootBranch().subtree(rootOffset)
|
// 1. path.front().first == rootBranch().subtree(rootOffset)
|
||||||
// 2. path[i].first == path[i-1].first.branch().subtree(path[i-1].second)
|
// 2. path[i].first == path[i-1].first.subtree(path[i-1].second)
|
||||||
// 3. path.size() == map->height.
|
// 3. path.size() == map->height.
|
||||||
//
|
//
|
||||||
// Thus, path.back() always refers to the current leaf node unless the root is
|
// Thus, path.back() always refers to the current leaf node unless the root is
|
||||||
@ -1138,14 +1134,14 @@ protected:
|
|||||||
return map->branched();
|
return map->branched();
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeRef pathNode(unsigned h) const { return path[h].first; }
|
IntervalMapImpl::NodeRef pathNode(unsigned h) const { return path[h].first; }
|
||||||
NodeRef &pathNode(unsigned h) { return path[h].first; }
|
IntervalMapImpl::NodeRef &pathNode(unsigned h) { return path[h].first; }
|
||||||
unsigned pathOffset(unsigned h) const { return path[h].second; }
|
unsigned pathOffset(unsigned h) const { return path[h].second; }
|
||||||
unsigned &pathOffset(unsigned h) { return path[h].second; }
|
unsigned &pathOffset(unsigned h) { return path[h].second; }
|
||||||
|
|
||||||
Leaf &treeLeaf() const {
|
Leaf &treeLeaf() const {
|
||||||
assert(branched() && path.size() == map->height);
|
assert(branched() && path.size() == map->height);
|
||||||
return path.back().first.leaf();
|
return path.back().first.get<Leaf>();
|
||||||
}
|
}
|
||||||
unsigned treeLeafSize() const {
|
unsigned treeLeafSize() const {
|
||||||
assert(branched() && path.size() == map->height);
|
assert(branched() && path.size() == map->height);
|
||||||
@ -1161,21 +1157,21 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the next node ptr for an incomplete path.
|
// Get the next node ptr for an incomplete path.
|
||||||
NodeRef pathNextDown() {
|
IntervalMapImpl::NodeRef pathNextDown() {
|
||||||
assert(path.size() < map->height && "Path is already complete");
|
assert(path.size() < map->height && "Path is already complete");
|
||||||
|
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
return map->rootBranch().subtree(rootOffset);
|
return map->rootBranch().subtree(rootOffset);
|
||||||
else
|
else
|
||||||
return path.back().first.branch().subtree(path.back().second);
|
return path.back().first.subtree(path.back().second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pathFillLeft();
|
void pathFillLeft();
|
||||||
void pathFillFind(KeyT x);
|
void pathFillFind(KeyT x);
|
||||||
void pathFillRight();
|
void pathFillRight();
|
||||||
|
|
||||||
NodeRef leftSibling(unsigned level) const;
|
IntervalMapImpl::NodeRef leftSibling(unsigned level) const;
|
||||||
NodeRef rightSibling(unsigned level) const;
|
IntervalMapImpl::NodeRef rightSibling(unsigned level) const;
|
||||||
|
|
||||||
void treeIncrement();
|
void treeIncrement();
|
||||||
void treeDecrement();
|
void treeDecrement();
|
||||||
@ -1300,10 +1296,10 @@ public:
|
|||||||
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::pathFillLeft() {
|
const_iterator::pathFillLeft() {
|
||||||
NodeRef NR = pathNextDown();
|
IntervalMapImpl::NodeRef NR = pathNextDown();
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
||||||
path.push_back(PathEntry(NR, 0));
|
path.push_back(PathEntry(NR, 0));
|
||||||
NR = NR.branch().subtree(0);
|
NR = NR.subtree(0);
|
||||||
}
|
}
|
||||||
path.push_back(PathEntry(NR, 0));
|
path.push_back(PathEntry(NR, 0));
|
||||||
}
|
}
|
||||||
@ -1312,24 +1308,24 @@ const_iterator::pathFillLeft() {
|
|||||||
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) {
|
||||||
NodeRef NR = pathNextDown();
|
IntervalMapImpl::NodeRef NR = pathNextDown();
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
||||||
unsigned p = NR.branch().safeFind(0, x);
|
unsigned p = NR.get<Branch>().safeFind(0, x);
|
||||||
path.push_back(PathEntry(NR, p));
|
path.push_back(PathEntry(NR, p));
|
||||||
NR = NR.branch().subtree(p);
|
NR = NR.subtree(p);
|
||||||
}
|
}
|
||||||
path.push_back(PathEntry(NR, NR.leaf().safeFind(0, x)));
|
path.push_back(PathEntry(NR, NR.get<Leaf>().safeFind(0, x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// pathFillRight - Complete path by adding rightmost entries.
|
// pathFillRight - Complete path by adding rightmost entries.
|
||||||
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::pathFillRight() {
|
const_iterator::pathFillRight() {
|
||||||
NodeRef NR = pathNextDown();
|
IntervalMapImpl::NodeRef NR = pathNextDown();
|
||||||
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
for (unsigned i = map->height - path.size() - 1; i; --i) {
|
||||||
unsigned p = NR.size() - 1;
|
unsigned p = NR.size() - 1;
|
||||||
path.push_back(PathEntry(NR, p));
|
path.push_back(PathEntry(NR, p));
|
||||||
NR = NR.branch().subtree(p);
|
NR = NR.subtree(p);
|
||||||
}
|
}
|
||||||
path.push_back(PathEntry(NR, NR.size() - 1));
|
path.push_back(PathEntry(NR, NR.size() - 1));
|
||||||
}
|
}
|
||||||
@ -1338,9 +1334,9 @@ const_iterator::pathFillRight() {
|
|||||||
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
||||||
/// @return The left sibling NodeRef, or NULL.
|
/// @return The left sibling NodeRef, or NULL.
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
typename IntervalMap<KeyT, ValT, N, Traits>::NodeRef
|
IntervalMapImpl::NodeRef IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::leftSibling(unsigned level) const {
|
const_iterator::leftSibling(unsigned level) const {
|
||||||
|
using namespace IntervalMapImpl;
|
||||||
assert(branched() && "Not at a branched node");
|
assert(branched() && "Not at a branched node");
|
||||||
assert(level <= path.size() && "Bad level");
|
assert(level <= path.size() && "Bad level");
|
||||||
|
|
||||||
@ -1355,12 +1351,12 @@ const_iterator::leftSibling(unsigned level) const {
|
|||||||
|
|
||||||
// NR is the subtree containing our left sibling.
|
// NR is the subtree containing our left sibling.
|
||||||
NodeRef NR = h ?
|
NodeRef NR = h ?
|
||||||
pathNode(h - 1).branch().subtree(pathOffset(h - 1) - 1) :
|
pathNode(h - 1).subtree(pathOffset(h - 1) - 1) :
|
||||||
map->rootBranch().subtree(rootOffset - 1);
|
map->rootBranch().subtree(rootOffset - 1);
|
||||||
|
|
||||||
// Keep right all the way down.
|
// Keep right all the way down.
|
||||||
for (; h != level; ++h)
|
for (; h != level; ++h)
|
||||||
NR = NR.branch().subtree(NR.size() - 1);
|
NR = NR.subtree(NR.size() - 1);
|
||||||
return NR;
|
return NR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1368,9 +1364,9 @@ const_iterator::leftSibling(unsigned level) const {
|
|||||||
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
/// @param level 0 is just below the root, map->height - 1 for the leaves.
|
||||||
/// @return The right sibling NodeRef, or NULL.
|
/// @return The right sibling NodeRef, or NULL.
|
||||||
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
template <typename KeyT, typename ValT, unsigned N, typename Traits>
|
||||||
typename IntervalMap<KeyT, ValT, N, Traits>::NodeRef
|
IntervalMapImpl::NodeRef IntervalMap<KeyT, ValT, N, Traits>::
|
||||||
IntervalMap<KeyT, ValT, N, Traits>::
|
|
||||||
const_iterator::rightSibling(unsigned level) const {
|
const_iterator::rightSibling(unsigned level) const {
|
||||||
|
using namespace IntervalMapImpl;
|
||||||
assert(branched() && "Not at a branched node");
|
assert(branched() && "Not at a branched node");
|
||||||
assert(level <= this->path.size() && "Bad level");
|
assert(level <= this->path.size() && "Bad level");
|
||||||
|
|
||||||
@ -1385,12 +1381,12 @@ const_iterator::rightSibling(unsigned level) const {
|
|||||||
|
|
||||||
// NR is the subtree containing our right sibling.
|
// NR is the subtree containing our right sibling.
|
||||||
NodeRef NR = h ?
|
NodeRef NR = h ?
|
||||||
pathNode(h - 1).branch().subtree(pathOffset(h - 1) + 1) :
|
pathNode(h - 1).subtree(pathOffset(h - 1) + 1) :
|
||||||
map->rootBranch().subtree(rootOffset + 1);
|
map->rootBranch().subtree(rootOffset + 1);
|
||||||
|
|
||||||
// Keep left all the way down.
|
// Keep left all the way down.
|
||||||
for (; h != level; ++h)
|
for (; h != level; ++h)
|
||||||
NR = NR.branch().subtree(0);
|
NR = NR.subtree(0);
|
||||||
return NR;
|
return NR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,7 +1489,7 @@ class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator {
|
|||||||
|
|
||||||
void setNodeSize(unsigned Level, unsigned Size);
|
void setNodeSize(unsigned Level, unsigned Size);
|
||||||
void setNodeStop(unsigned Level, KeyT Stop);
|
void setNodeStop(unsigned Level, KeyT Stop);
|
||||||
void insertNode(unsigned Level, NodeRef Node, KeyT Stop);
|
void insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
|
||||||
void overflowLeaf();
|
void overflowLeaf();
|
||||||
void treeInsert(KeyT a, KeyT b, ValT y);
|
void treeInsert(KeyT a, KeyT b, ValT y);
|
||||||
|
|
||||||
@ -1512,8 +1508,7 @@ void IntervalMap<KeyT, ValT, N, Traits>::
|
|||||||
iterator::setNodeSize(unsigned Level, unsigned Size) {
|
iterator::setNodeSize(unsigned Level, unsigned Size) {
|
||||||
this->pathNode(Level).setSize(Size);
|
this->pathNode(Level).setSize(Size);
|
||||||
if (Level)
|
if (Level)
|
||||||
this->pathNode(Level-1).branch()
|
this->pathNode(Level-1).subtree(this->pathOffset(Level-1)).setSize(Size);
|
||||||
.subtree(this->pathOffset(Level-1)).setSize(Size);
|
|
||||||
else
|
else
|
||||||
this->map->rootBranch().subtree(this->rootOffset).setSize(Size);
|
this->map->rootBranch().subtree(this->rootOffset).setSize(Size);
|
||||||
}
|
}
|
||||||
@ -1523,7 +1518,8 @@ 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--) {
|
while (Level--) {
|
||||||
this->pathNode(Level).branch().stop(this->pathOffset(Level)) = Stop;
|
this->pathNode(Level).template get<Branch>()
|
||||||
|
.stop(this->pathOffset(Level)) = Stop;
|
||||||
if (this->pathOffset(Level) != this->pathNode(Level).size() - 1)
|
if (this->pathOffset(Level) != this->pathNode(Level).size() - 1)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1534,7 +1530,7 @@ iterator::setNodeStop(unsigned Level, KeyT Stop) {
|
|||||||
/// Leave the current path pointing at the new node.
|
/// Leave the current path pointing at the new node.
|
||||||
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::insertNode(unsigned Level, NodeRef Node, KeyT Stop) {
|
iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
|
||||||
if (!Level) {
|
if (!Level) {
|
||||||
// Insert into the root branch node.
|
// Insert into the root branch node.
|
||||||
IntervalMap &IM = *this->map;
|
IntervalMap &IM = *this->map;
|
||||||
@ -1559,10 +1555,10 @@ iterator::insertNode(unsigned Level, NodeRef Node, KeyT Stop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert into the branch node at level-1.
|
// Insert into the branch node at level-1.
|
||||||
NodeRef NR = this->pathNode(Level-1);
|
IntervalMapImpl::NodeRef NR = this->pathNode(Level-1);
|
||||||
unsigned Offset = this->pathOffset(Level-1);
|
unsigned Offset = this->pathOffset(Level-1);
|
||||||
assert(NR.size() < Branch::Capacity && "Branch overflow");
|
assert(NR.size() < Branch::Capacity && "Branch overflow");
|
||||||
NR.branch().insert(Offset, NR.size(), Node, Stop);
|
NR.get<Branch>().insert(Offset, NR.size(), Node, Stop);
|
||||||
setNodeSize(Level - 1, NR.size() + 1);
|
setNodeSize(Level - 1, NR.size() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1624,6 +1620,7 @@ iterator::treeInsert(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::overflowLeaf() {
|
iterator::overflowLeaf() {
|
||||||
|
using namespace IntervalMapImpl;
|
||||||
unsigned CurSize[4];
|
unsigned CurSize[4];
|
||||||
Leaf *Node[4];
|
Leaf *Node[4];
|
||||||
unsigned Nodes = 0;
|
unsigned Nodes = 0;
|
||||||
@ -1634,7 +1631,7 @@ iterator::overflowLeaf() {
|
|||||||
NodeRef LeftSib = this->leftSibling(this->map->height-1);
|
NodeRef LeftSib = this->leftSibling(this->map->height-1);
|
||||||
if (LeftSib) {
|
if (LeftSib) {
|
||||||
Offset += Elements = CurSize[Nodes] = LeftSib.size();
|
Offset += Elements = CurSize[Nodes] = LeftSib.size();
|
||||||
Node[Nodes++] = &LeftSib.leaf();
|
Node[Nodes++] = &LeftSib.get<Leaf>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current leaf node.
|
// Current leaf node.
|
||||||
@ -1645,7 +1642,7 @@ iterator::overflowLeaf() {
|
|||||||
NodeRef RightSib = this->rightSibling(this->map->height-1);
|
NodeRef RightSib = this->rightSibling(this->map->height-1);
|
||||||
if (RightSib) {
|
if (RightSib) {
|
||||||
Offset += Elements = CurSize[Nodes] = RightSib.size();
|
Offset += Elements = CurSize[Nodes] = RightSib.size();
|
||||||
Node[Nodes++] = &RightSib.leaf();
|
Node[Nodes++] = &RightSib.get<Leaf>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we need to allocate a new node?
|
// Do we need to allocate a new node?
|
||||||
@ -1662,8 +1659,7 @@ iterator::overflowLeaf() {
|
|||||||
|
|
||||||
// Compute the new element distribution.
|
// Compute the new element distribution.
|
||||||
unsigned NewSize[4];
|
unsigned NewSize[4];
|
||||||
IdxPair NewOffset =
|
IdxPair NewOffset = distribute(Nodes, Elements, Leaf::Capacity,
|
||||||
IntervalMapImpl::distribute(Nodes, Elements, Leaf::Capacity,
|
|
||||||
CurSize, NewSize, Offset, true);
|
CurSize, NewSize, Offset, true);
|
||||||
|
|
||||||
// Move current location to the leftmost node.
|
// Move current location to the leftmost node.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user