aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2010-11-26 06:54:20 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2010-11-26 06:54:20 +0000
commit53bb5c009b04f4a5dd2388b25efe88b5579b282c (patch)
tree6709e219666f07842bc241ce259ae3198d0667a3
parentbf77baf19cfbc7a8795d9683e9b9ec894b9ff8c9 (diff)
Add B+-tree test case that creates a height 3 tree with a smaller root node.
Change temporary debugging code to write a dot file directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120171 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ADT/IntervalMap.h46
-rw-r--r--unittests/ADT/IntervalMapTest.cpp51
2 files changed, 81 insertions, 16 deletions
diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h
index dcc30f033c..8eb5487b0e 100644
--- a/include/llvm/ADT/IntervalMap.h
+++ b/include/llvm/ADT/IntervalMap.h
@@ -585,11 +585,11 @@ public:
unsigned extendStop(unsigned i, unsigned Size, KeyT b);
#ifndef NDEBUG
- void dump(unsigned Size) {
- errs() << " N" << this << " [shape=record label=\"{ " << Size << '/' << N;
+ void dump(raw_ostream &OS, unsigned Size) {
+ OS << " N" << this << " [shape=record label=\"{ " << Size << '/' << N;
for (unsigned i = 0; i != Size; ++i)
- errs() << " | {" << start(i) << '-' << stop(i) << "|" << value(i) << '}';
- errs() << "}\"];\n";
+ OS << " | {" << start(i) << '-' << stop(i) << "|" << value(i) << '}';
+ OS << "}\"];\n";
}
#endif
@@ -771,14 +771,14 @@ public:
}
#ifndef NDEBUG
- void dump(unsigned Size) {
- errs() << " N" << this << " [shape=record label=\"" << Size << '/' << N;
+ void dump(raw_ostream &OS, unsigned Size) {
+ OS << " N" << this << " [shape=record label=\"" << Size << '/' << N;
for (unsigned i = 0; i != Size; ++i)
- errs() << " | <s" << i << "> " << stop(i);
- errs() << "\"];\n";
+ OS << " | <s" << i << "> " << stop(i);
+ OS << "\"];\n";
for (unsigned i = 0; i != Size; ++i)
- errs() << " N" << this << ":s" << i << " -> N"
- << &subtree(i).template get<BranchNode>() << ";\n";
+ OS << " N" << this << ":s" << i << " -> N"
+ << &subtree(i).template get<BranchNode>() << ";\n";
}
#endif
@@ -851,6 +851,12 @@ public:
return path[Level].subtree(path[Level].offset);
}
+ /// reset - Reset cached information about node(Level) from subtree(Level -1).
+ /// @param Level 1..height. THe node to update after parent node changed.
+ void reset(unsigned Level) {
+ path[Level] = Entry(subtree(Level - 1), offset(Level));
+ }
+
/// push - Add entry to path.
/// @param Node Node to add, should be subtree(path.size()-1).
/// @param Offset Offset into Node.
@@ -1167,6 +1173,7 @@ public:
}
#ifndef NDEBUG
+ raw_ostream *OS;
void dump();
void dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height);
#endif
@@ -1316,21 +1323,24 @@ template <typename KeyT, typename ValT, unsigned N, typename Traits>
void IntervalMap<KeyT, ValT, N, Traits>::
dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height) {
if (Height)
- Node.get<Branch>().dump(Node.size());
+ Node.get<Branch>().dump(*OS, Node.size());
else
- Node.get<Leaf>().dump(Node.size());
+ Node.get<Leaf>().dump(*OS, Node.size());
}
template <typename KeyT, typename ValT, unsigned N, typename Traits>
void IntervalMap<KeyT, ValT, N, Traits>::
dump() {
- errs() << "digraph {\n";
+ std::string errors;
+ raw_fd_ostream ofs("tree.dot", errors);
+ OS = &ofs;
+ ofs << "digraph {\n";
if (branched())
- rootBranch().dump(rootSize);
+ rootBranch().dump(ofs, rootSize);
else
- rootLeaf().dump(rootSize);
+ rootLeaf().dump(ofs, rootSize);
visitNodes(&IntervalMap::dumpNode);
- errs() << "}\n";
+ ofs << "}\n";
}
#endif
@@ -1557,6 +1567,7 @@ iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
if (IM.rootSize < RootBranch::Capacity) {
IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop);
P.setSize(0, ++IM.rootSize);
+ P.reset(Level);
return SplitRoot;
}
@@ -1581,6 +1592,9 @@ iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
}
P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop);
P.setSize(Level, P.size(Level) + 1);
+ if (P.atLastBranch(Level))
+ setNodeStop(Level, Stop);
+ P.reset(Level + 1);
return SplitRoot;
}
diff --git a/unittests/ADT/IntervalMapTest.cpp b/unittests/ADT/IntervalMapTest.cpp
index d4b2f52b50..36476a4cad 100644
--- a/unittests/ADT/IntervalMapTest.cpp
+++ b/unittests/ADT/IntervalMapTest.cpp
@@ -15,6 +15,7 @@ using namespace llvm;
namespace {
typedef IntervalMap<unsigned, unsigned> UUMap;
+typedef IntervalMap<unsigned, unsigned, 4> UU4Map;
// Empty map tests
TEST(IntervalMapTest, EmptyMap) {
@@ -373,4 +374,54 @@ TEST(IntervalMapTest, Branched) {
EXPECT_TRUE(map.begin() == map.end());
}
+// Branched, high, non-coalescing tests.
+TEST(IntervalMapTest, Branched2) {
+ UU4Map::Allocator allocator;
+ UU4Map map(allocator);
+
+ // Insert enough intervals to force a height >= 2 tree.
+ for (unsigned i = 1; i < 1000; ++i)
+ map.insert(10*i, 10*i+5, i);
+
+ // Tree limits.
+ EXPECT_FALSE(map.empty());
+ EXPECT_EQ(10u, map.start());
+ EXPECT_EQ(9995u, map.stop());
+
+ // Tree lookup.
+ for (unsigned i = 1; i < 1000; ++i) {
+ EXPECT_EQ(0u, map.lookup(10*i-1));
+ EXPECT_EQ(i, map.lookup(10*i));
+ EXPECT_EQ(i, map.lookup(10*i+5));
+ EXPECT_EQ(0u, map.lookup(10*i+6));
+ }
+
+ // Forward iteration.
+ UU4Map::iterator I = map.begin();
+ for (unsigned i = 1; i < 1000; ++i) {
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ ++I;
+ }
+ EXPECT_FALSE(I.valid());
+ EXPECT_TRUE(I == map.end());
+
+ // Backwards iteration.
+ for (unsigned i = 999; i; --i) {
+ --I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ }
+ EXPECT_TRUE(I == map.begin());
+
+ // Test clear() on branched map.
+ map.clear();
+ EXPECT_TRUE(map.empty());
+ EXPECT_TRUE(map.begin() == map.end());
+}
+
} // namespace