#include <libpspp/tower.h>
+#include <limits.h>
+
#include <libpspp/assertion.h>
#include <libpspp/compiler.h>
static struct tower_node *abt_to_tower_node (const struct abt_node *);
static struct tower_node *first_node (const struct tower *);
+static struct tower_node *last_node (const struct tower *);
static struct tower_node *next_node (const struct tower *,
const struct tower_node *);
+static struct tower_node *prev_node (const struct tower *,
+ const struct tower_node *);
static unsigned long int get_subtree_height (const struct abt_node *);
static void reaugment_tower_node (struct abt_node *,
const struct abt_node *,
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. */
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. */
{
struct tower_node *next = next_node (t, node);
abt_delete (&t->abt, &node->abt_node);
+ t->cache_bottom = ULONG_MAX;
return next;
}
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
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
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 (;;)
if (height < node_height)
{
/* Our goal height is in P. */
+ t->cache = node;
+ t->cache_bottom = *node_start;
return node;
}
else
return first_node (t);
}
+/* Returns the node at the top of tower T, or a null pointer if T
+ is empty. */
+struct tower_node *
+tower_last (const struct tower *t)
+{
+ return last_node (t);
+}
+
/* If NODE is nonnull, returns the node just above NODE in tower
T, or a null pointer if NODE is the topmost node in T.
If NODE is null, acts like tower_first. */
{
return node != NULL ? next_node (t, node) : first_node (t);
}
+
+/* If NODE is nonnull, returns the node just below NODE in tower
+ T, or a null pointer if NODE is the bottommost node in T.
+ If NODE is null, acts like tower_last. */
+struct tower_node *
+tower_prev (const struct tower *t, const struct tower_node *node)
+{
+ return node != NULL ? prev_node (t, node) : last_node (t);
+}
\f
/* Returns the tower node corresponding to the given ABT_NODE. */
static struct tower_node *
return abt_data (abt_node, struct tower_node, abt_node);
}
+/* Returns the tower node corresponding to the given ABT_NODE. */
+static struct tower_node *
+abt_to_tower_node_null (const struct abt_node *abt_node)
+{
+ return abt_node != NULL ? abt_to_tower_node (abt_node) : NULL;
+}
+
/* Returns the first node in TOWER. */
static struct tower_node *
first_node (const struct tower *t)
{
- struct abt_node *abt_node = abt_first (&t->abt);
- return abt_node != NULL ? abt_to_tower_node (abt_node) : NULL;
+ return abt_to_tower_node_null (abt_first (&t->abt));
+}
+
+/* Returns the first node in TOWER. */
+static struct tower_node *
+last_node (const struct tower *t)
+{
+ return abt_to_tower_node_null (abt_last (&t->abt));
}
/* Returns the next node in TOWER after NODE. */
static struct tower_node *
next_node (const struct tower *t, const struct tower_node *node)
{
- struct abt_node *abt_node = abt_next (&t->abt, &node->abt_node);
- return abt_node != NULL ? abt_to_tower_node (abt_node) : NULL;
+ return abt_to_tower_node_null (abt_next (&t->abt, &node->abt_node));
+}
+
+/* Returns the previous node in TOWER before NODE. */
+static struct tower_node *
+prev_node (const struct tower *t, const struct tower_node *node)
+{
+ return abt_to_tower_node_null (abt_prev (&t->abt, &node->abt_node));
}
/* Returns the total height of the nodes in the subtree rooted at