* tower.c: Cache repeated lookups of a single tower element. This
authorBen Pfaff <blp@gnu.org>
Mon, 4 Jun 2007 01:29:08 +0000 (01:29 +0000)
committerBen Pfaff <blp@gnu.org>
Mon, 4 Jun 2007 01:29:08 +0000 (01:29 +0000)
turns such lookups into O(1) operations without harming the big-O
of other operations.

* tower.h (struct tower): Add members for caching.

src/libpspp/ChangeLog
src/libpspp/tower.c
src/libpspp/tower.h

index c125ac413bf7661bfd7edd384c3fa083e4b258e5..29acbae1f3b6ca9e0ce51df18e7a3b75dac1a6f4 100644 (file)
@@ -1,5 +1,11 @@
 2007-06-03  Ben Pfaff  <blp@gnu.org>
 
+       * tower.c: Cache repeated lookups of a single tower element.  This
+       turns such lookups into O(1) operations without harming the big-O
+       of other operations.
+
+       * tower.h (struct tower): Add members for caching.
+
        * range-set.c (range_set_clone): New function.
 
        * array.c (insert_range): New function.
index ead91e61a7093beda05e3708256be0ed9222b7d0..79801b3a07d774de0f4945c28c531bc54ac62c5a 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <libpspp/tower.h>
 
+#include <limits.h>
+
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 
@@ -38,6 +40,7 @@ void
 tower_init (struct tower *t) 
 {
   abt_init (&t->abt, NULL, reaugment_tower_node, NULL);
+  t->cache_bottom = ULONG_MAX;
 }
 
 /* Returns true if T contains no nodes, false otherwise. */
@@ -64,6 +67,7 @@ tower_insert (struct tower *t, unsigned long height, struct tower_node *new,
   new->height = height;
   abt_insert_before (&t->abt, under ? &under->abt_node : NULL,
                      &new->abt_node);
+  t->cache_bottom = ULONG_MAX;
 }
 
 /* Deletes NODE from tower T. */
@@ -72,6 +76,7 @@ tower_delete (struct tower *t, struct tower_node *node)
 {
   struct tower_node *next = next_node (t, node);
   abt_delete (&t->abt, &node->abt_node);
+  t->cache_bottom = ULONG_MAX;
   return next;
 }
 
@@ -83,6 +88,7 @@ tower_resize (struct tower *t, struct tower_node *node,
   assert (new_height > 0);
   node->height = new_height;
   abt_reaugmented (&t->abt, &node->abt_node);
+  t->cache_bottom = ULONG_MAX;
 }
 
 /* Removes nodes FIRST through LAST (exclusive) from tower SRC
@@ -110,6 +116,7 @@ tower_splice (struct tower *dst, struct tower_node *under,
       abt_insert_before (&dst->abt, under ? &under->abt_node : NULL,
                          &first->abt_node);
     }
+  dst->cache_bottom = src->cache_bottom = ULONG_MAX;
 }
 
 /* Returns the node at the given HEIGHT from the bottom of tower
@@ -118,14 +125,21 @@ tower_splice (struct tower *dst, struct tower_node *under,
    of the returned node, which may be less than HEIGHT if HEIGHT
    refers to the middle of a node instead of its bottom. */
 struct tower_node *
-tower_lookup (const struct tower *t,
+tower_lookup (const struct tower *t_,
               unsigned long height,
               unsigned long *node_start) 
 {
+  struct tower *t = (struct tower *) t_;
   struct abt_node *p;
 
   assert (height < tower_height (t));
 
+  if (height >= t->cache_bottom && height - t->cache_bottom < t->cache->height)
+    {
+      *node_start = t->cache_bottom;
+      return t->cache; 
+    }
+
   *node_start = 0;
   p = t->abt.root;
   for (;;)
@@ -147,6 +161,8 @@ tower_lookup (const struct tower *t,
           if (height < node_height) 
             {
               /* Our goal height is in P. */
+              t->cache = node;
+              t->cache_bottom = *node_start;
               return node; 
             }
           else 
index e0ee12a758229bef02e9ae934c0437ee44b3a6bc..5a4c08e204f714aa334c054a73db8867518594f3 100644 (file)
@@ -74,7 +74,9 @@ tower_node_get_height (const struct tower_node *node)
 /* A tower. */
 struct tower 
   {
-    struct abt abt;              /* Tree. */
+    struct abt abt;                   /* Tree. */
+    struct tower_node *cache;         /* Cache node. */
+    unsigned long int cache_bottom;   /* Height of cache's bottom. */
   };
 
 void tower_init (struct tower *);