Add B+-tree test case that creates a height 3 tree with a smaller root node.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 26 Nov 2010 06:54:20 +0000 (06:54 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 26 Nov 2010 06:54:20 +0000 (06:54 +0000)
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

include/llvm/ADT/IntervalMap.h
unittests/ADT/IntervalMapTest.cpp

index dcc30f033c853c1533d8b42433763f67f26ec70b..8eb5487b0e4674274f3149556910c2f2617e56ea 100644 (file)
@@ -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;
 }
 
index d4b2f52b50c4ff23abfd77d6a2ae55137c3414de..36476a4cad9000d6b66eb20ee5e5cd302afd6d5b 100644 (file)
@@ -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