1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "libpspp/tower.h"
23 #include "libpspp/assertion.h"
24 #include "libpspp/cast.h"
25 #include "libpspp/compiler.h"
27 static struct tower_node *abt_to_tower_node (const struct abt_node *);
28 static struct tower_node *first_node (const struct tower *);
29 static struct tower_node *last_node (const struct tower *);
30 static struct tower_node *next_node (const struct tower *,
31 const struct tower_node *);
32 static struct tower_node *prev_node (const struct tower *,
33 const struct tower_node *);
34 static unsigned long int get_subtree_size (const struct abt_node *);
35 static unsigned long int get_subtree_count (const struct abt_node *);
36 static void reaugment_tower_node (struct abt_node *,
37 const struct abt_node *,
38 const struct abt_node *,
41 /* Returns the height of the bottom of the given tower NODE.
43 The performance of this function is O(lg n) in the number of
44 nodes in the tower. It is often possible to avoid calling
45 this function, either by taking advantage of the NODE_START
46 parameter to tower_lookup or by incrementally keeping track of
47 height while iterating through a tower. In the former case
48 the asymptotic performance is no different, since tower_lookup
49 is also O(lg n), but in the latter case performance improves
50 from O(lg n) to O(1). */
52 tower_node_get_level (const struct tower_node *node)
54 const struct abt_node *p = &node->abt_node;
55 unsigned long level = get_subtree_size (p->down[0]);
58 if (p == p->up->down[1])
59 level += (get_subtree_size (p->up->down[0])
60 + abt_to_tower_node (p->up)->size);
66 /* Returns the index of the given tower NODE.
68 The performance of this function is O(lg n) in the number of
69 nodes in the tower. It is often possible to avoid calling
70 this function by keeping track of the index while iterating
71 through a tower. Doing so when possible will improve
72 performance from O(lg n) to O(1). */
74 tower_node_get_index (const struct tower_node *node)
76 const struct abt_node *p = &node->abt_node;
77 unsigned long index = get_subtree_count (p->down[0]);
80 if (p == p->up->down[1])
81 index += get_subtree_count (p->up->down[0]) + 1;
87 /* Initializes T as an empty tower. */
89 tower_init (struct tower *t)
91 abt_init (&t->abt, NULL, reaugment_tower_node, NULL);
92 t->cache_bottom = ULONG_MAX;
95 /* Returns true if T contains no nodes, false otherwise. */
97 tower_is_empty (const struct tower *t)
99 return t->abt.root == NULL;
102 /* Returns the number of nodes in tower T. */
104 tower_count (const struct tower *t)
106 return get_subtree_count (t->abt.root);
109 /* Returns the total height of tower T. */
111 tower_height (const struct tower *t)
113 return get_subtree_size (t->abt.root);
116 /* Inserts node NEW with the specified SIZE into T just below
117 node UNDER, or at the top of T if UNDER is a null pointer. */
119 tower_insert (struct tower *t, unsigned long size, struct tower_node *new,
120 struct tower_node *under)
124 abt_insert_before (&t->abt, under ? &under->abt_node : NULL,
126 t->cache_bottom = ULONG_MAX;
129 /* Deletes NODE from tower T. */
131 tower_delete (struct tower *t, struct tower_node *node)
133 struct tower_node *next = next_node (t, node);
134 abt_delete (&t->abt, &node->abt_node);
135 t->cache_bottom = ULONG_MAX;
139 /* Changes the size of NODE in tower T to NEW_SIZE. */
141 tower_resize (struct tower *t, struct tower_node *node,
142 unsigned long new_size)
144 assert (new_size > 0);
145 node->size = new_size;
146 abt_reaugmented (&t->abt, &node->abt_node);
147 t->cache_bottom = ULONG_MAX;
150 /* Removes nodes FIRST through LAST (exclusive) from tower SRC
151 and splices them into tower DST just below node UNDER, or at
152 the top of DST if UNDER is a null pointer.
154 It might be better to implement an abt_splice function and
155 turn this into a wrapper, but the asymptotic performance would
158 tower_splice (struct tower *dst, struct tower_node *under,
160 struct tower_node *first, struct tower_node *last)
162 struct tower_node *next;
164 /* Conceptually, DST == SRC is valid.
165 Practically, it's more difficult to get it right, and our
166 client code doesn't need it. */
169 for (; first != last; first = next)
171 next = tower_delete (src, first);
172 abt_insert_before (&dst->abt, under ? &under->abt_node : NULL,
175 dst->cache_bottom = src->cache_bottom = ULONG_MAX;
178 /* Returns the node at the given HEIGHT from the bottom of tower
179 T. HEIGHT must be less than T's height (as returned by
180 tower_height). Stores in *NODE_START the height of the bottom
181 of the returned node, which may be less than HEIGHT if HEIGHT
182 refers to the middle of a node instead of its bottom. */
184 tower_lookup (const struct tower *t_,
185 unsigned long height,
186 unsigned long *node_start)
188 struct tower *t = CONST_CAST (struct tower *, t_);
191 assert (height < tower_height (t));
193 if (height >= t->cache_bottom && height - t->cache_bottom < t->cache->size)
195 *node_start = t->cache_bottom;
203 unsigned long left_size = get_subtree_size (p->down[0]);
204 if (height < left_size)
206 /* Our goal height must lie within the left subtree. */
211 /* Our goal height cannot be in the left subtree. */
212 struct tower_node *node = abt_to_tower_node (p);
213 unsigned long int node_size = node->size;
216 *node_start += left_size;
217 if (height < node_size)
219 /* Our goal height is in P. */
221 t->cache_bottom = *node_start;
226 /* Our goal height is in the right subtree. */
229 *node_start += node_size;
235 /* Returns the node with the given 0-based INDEX, which must be
236 less than the number of nodes in T (as returned by
239 tower_get (const struct tower *t_, unsigned long int index)
241 struct tower *t = CONST_CAST (struct tower *, t_);
244 assert (index < tower_count (t));
249 unsigned long left_count = get_subtree_count (p->down[0]);
250 if (index < left_count)
252 else if (index == left_count)
253 return abt_to_tower_node (p);
257 index -= left_count + 1;
262 /* Returns the node at height 0 in tower T, or a null pointer if
265 tower_first (const struct tower *t)
267 return first_node (t);
270 /* Returns the node at the top of tower T, or a null pointer if T
273 tower_last (const struct tower *t)
275 return last_node (t);
278 /* If NODE is nonnull, returns the node just above NODE in tower
279 T, or a null pointer if NODE is the topmost node in T.
280 If NODE is null, acts like tower_first. */
282 tower_next (const struct tower *t, const struct tower_node *node)
284 return node != NULL ? next_node (t, node) : first_node (t);
287 /* If NODE is nonnull, returns the node just below NODE in tower
288 T, or a null pointer if NODE is the bottommost node in T.
289 If NODE is null, acts like tower_last. */
291 tower_prev (const struct tower *t, const struct tower_node *node)
293 return node != NULL ? prev_node (t, node) : last_node (t);
296 /* Returns the tower node corresponding to the given ABT_NODE. */
297 static struct tower_node *
298 abt_to_tower_node (const struct abt_node *abt_node)
300 return abt_data (abt_node, struct tower_node, abt_node);
303 /* Returns the tower node corresponding to the given ABT_NODE. */
304 static struct tower_node *
305 abt_to_tower_node_null (const struct abt_node *abt_node)
307 return abt_node != NULL ? abt_to_tower_node (abt_node) : NULL;
310 /* Returns the first node in TOWER. */
311 static struct tower_node *
312 first_node (const struct tower *t)
314 return abt_to_tower_node_null (abt_first (&t->abt));
317 /* Returns the first node in TOWER. */
318 static struct tower_node *
319 last_node (const struct tower *t)
321 return abt_to_tower_node_null (abt_last (&t->abt));
324 /* Returns the next node in TOWER after NODE. */
325 static struct tower_node *
326 next_node (const struct tower *t, const struct tower_node *node)
328 return abt_to_tower_node_null (abt_next (&t->abt, &node->abt_node));
331 /* Returns the previous node in TOWER before NODE. */
332 static struct tower_node *
333 prev_node (const struct tower *t, const struct tower_node *node)
335 return abt_to_tower_node_null (abt_prev (&t->abt, &node->abt_node));
338 /* Returns the total size of the nodes in the subtree rooted at
339 P, or 0 if P is null. */
340 static unsigned long int
341 get_subtree_size (const struct abt_node *p)
343 return p != NULL ? abt_to_tower_node (p)->subtree_size : 0;
346 /* Returns the total number of nodes in the subtree rooted at P,
347 or 0 if P is null. */
348 static unsigned long int
349 get_subtree_count (const struct abt_node *p)
351 return p != NULL ? abt_to_tower_node (p)->subtree_count : 0;
354 /* Recalculates the subtree_size of NODE based on its LEFT and
355 RIGHT children's subtree_sizes. */
357 reaugment_tower_node (struct abt_node *node_,
358 const struct abt_node *left,
359 const struct abt_node *right,
360 const void *aux UNUSED)
362 struct tower_node *node = abt_to_tower_node (node_);
363 node->subtree_size = node->size;
364 node->subtree_count = 1;
367 struct tower_node *left_node = abt_to_tower_node (left);
368 node->subtree_size += left_node->subtree_size;
369 node->subtree_count += left_node->subtree_count;
373 struct tower_node *right_node = abt_to_tower_node (right);
374 node->subtree_size += right_node->subtree_size;
375 node->subtree_count += right_node->subtree_count;