1 #include <libpspp/bt.h>
12 /* Exit with a failure code.
13 (Place a breakpoint on this function while debugging.) */
20 /* If OK is not true, prints a message about failure on the
21 current source file and the given LINE and terminates. */
23 check_func (bool ok
, int line
)
27 fprintf (stderr
, "%s:%d: check failed\n", __FILE__
, line
);
32 /* Verifies that EXPR evaluates to true.
33 If not, prints a message citing the calling line number and
35 #define check(EXPR) check_func ((EXPR), __LINE__)
37 /* Prints a message about memory exhaustion and exits with a
42 printf ("virtual memory exhausted\n");
46 /* Allocates and returns N bytes of memory. */
63 xmemdup (const void *p
, size_t n
)
65 void *q
= xmalloc (n
);
70 /* Allocates and returns N * M bytes of memory. */
72 xnmalloc (size_t n
, size_t m
)
74 if ((size_t) -1 / m
<= n
)
76 return xmalloc (n
* m
);
79 /* Node type and support routines. */
81 /* Test data element. */
84 struct bt_node node
; /* Embedded binary tree element. */
85 int data
; /* Primary value. */
90 /* Returns the `struct element' that NODE is embedded within. */
91 static struct element
*
92 bt_node_to_element (const struct bt_node
*node
)
94 return bt_data (node
, struct element
, node
);
97 /* Compares the `x' values in A and B and returns a strcmp-type
98 return value. Verifies that AUX points to aux_data. */
100 compare_elements (const struct bt_node
*a_
, const struct bt_node
*b_
,
103 const struct element
*a
= bt_node_to_element (a_
);
104 const struct element
*b
= bt_node_to_element (b_
);
106 check (aux
== &aux_data
);
107 return a
->data
< b
->data
? -1 : a
->data
> b
->data
;
110 /* Compares A and B and returns a strcmp-type return value. */
112 compare_ints_noaux (const void *a_
, const void *b_
)
117 return *a
< *b
? -1 : *a
> *b
;
120 /* Swaps *A and *B. */
122 swap (int *a
, int *b
)
129 /* Reverses the order of the CNT integers starting at VALUES. */
131 reverse (int *values
, size_t cnt
)
137 swap (&values
[i
++], &values
[--j
]);
140 /* Arranges the CNT elements in VALUES into the lexicographically
141 next greater permutation. Returns true if successful.
142 If VALUES is already the lexicographically greatest
143 permutation of its elements (i.e. ordered from greatest to
144 smallest), arranges them into the lexicographically least
145 permutation (i.e. ordered from smallest to largest) and
148 next_permutation (int *values
, size_t cnt
)
156 if (values
[i
] < values
[i
+ 1])
159 for (j
= cnt
- 1; values
[i
] >= values
[j
]; j
--)
161 swap (values
+ i
, values
+ j
);
162 reverse (values
+ (i
+ 1), cnt
- (i
+ 1));
167 reverse (values
, cnt
);
175 factorial (unsigned int n
)
177 unsigned int value
= 1;
183 /* Randomly shuffles the CNT elements in ARRAY, each of which is
184 SIZE bytes in size. */
186 random_shuffle (void *array_
, size_t cnt
, size_t size
)
188 char *array
= array_
;
189 char *tmp
= xmalloc (size
);
192 for (i
= 0; i
< cnt
; i
++)
194 size_t j
= rand () % (cnt
- i
) + i
;
197 memcpy (tmp
, array
+ j
* size
, size
);
198 memcpy (array
+ j
* size
, array
+ i
* size
, size
);
199 memcpy (array
+ i
* size
, tmp
, size
);
206 /* Calculates floor(log(n)/log(sqrt(2))). */
208 calculate_h_alpha (size_t n
)
210 size_t thresholds
[] =
212 0, 2, 2, 3, 4, 6, 8, 12, 16, 23, 32, 46, 64, 91, 128, 182, 256, 363,
213 512, 725, 1024, 1449, 2048, 2897, 4096, 5793, 8192, 11586, 16384,
214 23171, 32768, 46341, 65536, 92682, 131072, 185364, 262144, 370728,
215 524288, 741456, 1048576, 1482911, 2097152, 2965821, 4194304, 5931642,
216 8388608, 11863284, 16777216, 23726567, 33554432, 47453133, 67108864,
217 94906266, 134217728, 189812532, 268435456, 379625063, 536870912,
218 759250125, 1073741824, 1518500250, 2147483648, 3037000500,
220 size_t threshold_cnt
= sizeof thresholds
/ sizeof *thresholds
;
223 for (i
= 0; i
< threshold_cnt
; i
++)
224 if (thresholds
[i
] > n
)
229 /* Returns the height of the tree rooted at NODE. */
231 get_height (struct bt_node
*node
)
237 int left
= get_height (node
->down
[0]);
238 int right
= get_height (node
->down
[1]);
239 return 1 + (left
> right
? left
: right
);
243 /* Checks that BT is loosely alpha-height balanced, that is, that
244 its height is no more than h_alpha(count) + 1, where
245 h_alpha(n) = floor(log(n)/log(1/alpha)). */
247 check_balance (struct bt
*bt
)
249 /* In the notation of the Galperin and Rivest paper (and of
250 CLR), the height of a tree is the number of edges in the
251 longest path from the root to a leaf, so we have to subtract
252 1 from our measured height. */
253 int height
= get_height (bt
->root
) - 1;
254 int max_height
= calculate_h_alpha (bt_count (bt
)) + 1;
255 check (height
<= max_height
);
258 /* Checks that BT contains the CNT ints in DATA, that its
259 structure is correct, and that certain operations on BT
260 produce the expected results. */
262 check_bt (struct bt
*bt
, const int data
[], size_t cnt
)
268 order
= xmemdup (data
, cnt
* sizeof *data
);
269 qsort (order
, cnt
, sizeof *order
, compare_ints_noaux
);
271 for (i
= 0; i
< cnt
; i
++)
277 p
= bt_find (bt
, &e
.node
);
279 p
= bt_insert (bt
, &e
.node
);
281 check (p
!= &e
.node
);
282 check (bt_node_to_element (p
)->data
== data
[i
]);
286 check (bt_find (bt
, &e
.node
) == NULL
);
292 check (bt_first (bt
) == NULL
);
293 check (bt_last (bt
) == NULL
);
294 check (bt_next (bt
, NULL
) == NULL
);
295 check (bt_prev (bt
, NULL
) == NULL
);
301 for (p
= bt_first (bt
), i
= 0; i
< cnt
; p
= bt_next (bt
, p
), i
++)
302 check (bt_node_to_element (p
)->data
== order
[i
]);
305 for (p
= bt_last (bt
), i
= 0; i
< cnt
; p
= bt_prev (bt
, p
), i
++)
306 check (bt_node_to_element (p
)->data
== order
[cnt
- i
- 1]);
313 /* Inserts the CNT values from 0 to CNT - 1 (inclusive) into an
314 BT in the order specified by INSERTIONS, then deletes them in
315 the order specified by DELETIONS, checking the BT's contents
316 for correctness after each operation. */
318 test_insert_delete (const int insertions
[],
319 const int deletions
[],
322 struct element
*elements
;
326 elements
= xnmalloc (cnt
, sizeof *elements
);
327 for (i
= 0; i
< cnt
; i
++)
328 elements
[i
].data
= i
;
330 bt_init (&bt
, compare_elements
, &aux_data
);
331 check_bt (&bt
, NULL
, 0);
332 for (i
= 0; i
< cnt
; i
++)
334 check (bt_insert (&bt
, &elements
[insertions
[i
]].node
) == NULL
);
335 check_bt (&bt
, insertions
, i
+ 1);
337 for (i
= 0; i
< cnt
; i
++)
339 bt_delete (&bt
, &elements
[deletions
[i
]].node
);
340 check_bt (&bt
, deletions
+ i
+ 1, cnt
- i
- 1);
346 /* Inserts values into an BT in each possible order, then
347 removes them in each possible order, up to a specified maximum
350 test_insert_any_remove_any (void)
352 const int max_elems
= 5;
355 for (cnt
= 0; cnt
<= max_elems
; cnt
++)
357 int *insertions
, *deletions
;
358 unsigned int ins_perm_cnt
;
361 insertions
= xnmalloc (cnt
, sizeof *insertions
);
362 deletions
= xnmalloc (cnt
, sizeof *deletions
);
363 for (i
= 0; i
< cnt
; i
++)
366 for (ins_perm_cnt
= 0;
367 ins_perm_cnt
== 0 || next_permutation (insertions
, cnt
);
370 unsigned int del_perm_cnt
;
373 for (i
= 0; i
< cnt
; i
++)
376 for (del_perm_cnt
= 0;
377 del_perm_cnt
== 0 || next_permutation (deletions
, cnt
);
379 test_insert_delete (insertions
, deletions
, cnt
);
381 check (del_perm_cnt
== factorial (cnt
));
383 check (ins_perm_cnt
== factorial (cnt
));
390 /* Inserts values into an BT in each possible order, then
391 removes them in the same order, up to a specified maximum
394 test_insert_any_remove_same (void)
396 const int max_elems
= 7;
399 for (cnt
= 0; cnt
<= max_elems
; cnt
++)
402 unsigned int permutation_cnt
;
405 values
= xnmalloc (cnt
, sizeof *values
);
406 for (i
= 0; i
< cnt
; i
++)
409 for (permutation_cnt
= 0;
410 permutation_cnt
== 0 || next_permutation (values
, cnt
);
412 test_insert_delete (values
, values
, cnt
);
413 check (permutation_cnt
== factorial (cnt
));
419 /* Inserts values into an BT in each possible order, then
420 removes them in reverse order, up to a specified maximum
423 test_insert_any_remove_reverse (void)
425 const int max_elems
= 7;
428 for (cnt
= 0; cnt
<= max_elems
; cnt
++)
430 int *insertions
, *deletions
;
431 unsigned int permutation_cnt
;
434 insertions
= xnmalloc (cnt
, sizeof *insertions
);
435 deletions
= xnmalloc (cnt
, sizeof *deletions
);
436 for (i
= 0; i
< cnt
; i
++)
439 for (permutation_cnt
= 0;
440 permutation_cnt
== 0 || next_permutation (insertions
, cnt
);
443 memcpy (deletions
, insertions
, sizeof *insertions
* cnt
);
444 reverse (deletions
, cnt
);
446 test_insert_delete (insertions
, deletions
, cnt
);
448 check (permutation_cnt
== factorial (cnt
));
455 /* Inserts and removes values in an BT in random orders. */
457 test_random_sequence (void)
459 const int max_elems
= 128;
460 const int max_trials
= 8;
463 for (cnt
= 0; cnt
<= max_elems
; cnt
+= 2)
465 int *insertions
, *deletions
;
469 insertions
= xnmalloc (cnt
, sizeof *insertions
);
470 deletions
= xnmalloc (cnt
, sizeof *deletions
);
471 for (i
= 0; i
< cnt
; i
++)
473 for (i
= 0; i
< cnt
; i
++)
476 for (trial
= 0; trial
< max_trials
; trial
++)
478 random_shuffle (insertions
, cnt
, sizeof *insertions
);
479 random_shuffle (deletions
, cnt
, sizeof *deletions
);
481 test_insert_delete (insertions
, deletions
, cnt
);
489 /* Inserts elements into an BT in ascending order. */
491 test_insert_ordered (void)
493 const int max_elems
= 1024;
494 struct element
*elements
;
499 bt_init (&bt
, compare_elements
, &aux_data
);
500 elements
= xnmalloc (max_elems
, sizeof *elements
);
501 values
= xnmalloc (max_elems
, sizeof *values
);
502 for (i
= 0; i
< max_elems
; i
++)
504 values
[i
] = elements
[i
].data
= i
;
505 check (bt_insert (&bt
, &elements
[i
].node
) == NULL
);
506 check_bt (&bt
, values
, i
+ 1);
512 /* Tests bt_find_ge and bt_find_le. */
514 test_find_ge_le (void)
516 const int max_elems
= 10;
517 struct element
*elements
;
519 unsigned int inc_pat
;
521 elements
= xnmalloc (max_elems
, sizeof *elements
);
522 values
= xnmalloc (max_elems
, sizeof *values
);
523 for (inc_pat
= 0; inc_pat
< (1u << max_elems
); inc_pat
++)
529 /* Insert the values in the pattern into BT. */
530 bt_init (&bt
, compare_elements
, &aux_data
);
531 for (i
= 0; i
< max_elems
; i
++)
532 if (inc_pat
& (1u << i
))
534 values
[elem_cnt
] = elements
[elem_cnt
].data
= i
;
535 check (bt_insert (&bt
, &elements
[elem_cnt
].node
) == NULL
);
538 check_bt (&bt
, values
, elem_cnt
);
540 /* Try find_ge and find_le for each possible element value. */
541 for (i
= -1; i
<= max_elems
; i
++)
544 struct bt_node
*ge
, *le
;
548 for (j
= 0; j
< elem_cnt
; j
++)
550 if (ge
== NULL
&& values
[j
] >= i
)
551 ge
= &elements
[j
].node
;
553 le
= &elements
[j
].node
;
557 check (bt_find_ge (&bt
, &tmp
.node
) == ge
);
558 check (bt_find_le (&bt
, &tmp
.node
) == le
);
565 /* Inserts elements into an BT, then moves the nodes around in
570 const int max_elems
= 128;
571 struct element
*e
[2];
577 bt_init (&bt
, compare_elements
, &aux_data
);
578 e
[0] = xnmalloc (max_elems
, sizeof *e
[0]);
579 e
[1] = xnmalloc (max_elems
, sizeof *e
[1]);
580 values
= xnmalloc (max_elems
, sizeof *values
);
582 for (i
= 0; i
< max_elems
; i
++)
584 values
[i
] = e
[cur
][i
].data
= i
;
585 check (bt_insert (&bt
, &e
[cur
][i
].node
) == NULL
);
586 check_bt (&bt
, values
, i
+ 1);
588 for (j
= 0; j
<= i
; j
++)
590 e
[!cur
][j
] = e
[cur
][j
];
591 bt_moved (&bt
, &e
[!cur
][j
].node
);
592 check_bt (&bt
, values
, i
+ 1);
601 /* Inserts values into an BT, then changes their values. */
605 const int max_elems
= 6;
608 for (cnt
= 0; cnt
<= max_elems
; cnt
++)
610 int *values
, *changed_values
;
611 struct element
*elements
;
612 unsigned int permutation_cnt
;
615 values
= xnmalloc (cnt
, sizeof *values
);
616 changed_values
= xnmalloc (cnt
, sizeof *changed_values
);
617 elements
= xnmalloc (cnt
, sizeof *elements
);
618 for (i
= 0; i
< cnt
; i
++)
621 for (permutation_cnt
= 0;
622 permutation_cnt
== 0 || next_permutation (values
, cnt
);
625 for (i
= 0; i
< cnt
; i
++)
628 for (j
= 0; j
<= cnt
; j
++)
631 struct bt_node
*changed_retval
;
633 bt_init (&bt
, compare_elements
, &aux_data
);
635 /* Add to BT in order. */
636 for (k
= 0; k
< cnt
; k
++)
639 elements
[n
].data
= n
;
640 check (bt_insert (&bt
, &elements
[n
].node
) == NULL
);
642 check_bt (&bt
, values
, cnt
);
644 /* Change value i to j. */
645 elements
[i
].data
= j
;
646 for (k
= 0; k
< cnt
; k
++)
647 changed_values
[k
] = k
;
648 changed_retval
= bt_changed (&bt
, &elements
[i
].node
);
649 if (i
!= j
&& j
< cnt
)
651 /* Will cause duplicate. */
652 check (changed_retval
== &elements
[j
].node
);
653 changed_values
[i
] = changed_values
[cnt
- 1];
654 check_bt (&bt
, changed_values
, cnt
- 1);
659 check (changed_retval
== NULL
);
660 changed_values
[i
] = j
;
661 check_bt (&bt
, changed_values
, cnt
);
666 check (permutation_cnt
== factorial (cnt
));
669 free (changed_values
);
679 const char *description
;
680 void (*function
) (void);
683 static const struct test tests
[] =
686 "insert-any-remove-any",
687 "insert any order, delete any order",
688 test_insert_any_remove_any
691 "insert-any-remove-same",
692 "insert any order, delete same order",
693 test_insert_any_remove_same
696 "insert-any-remove-reverse",
697 "insert any order, delete reverse order",
698 test_insert_any_remove_reverse
702 "insert and delete in random sequence",
707 "insert in ascending order",
712 "find_ge and find_le",
717 "move elements around in memory",
722 "change key data in nodes",
727 enum { N_TESTS
= sizeof tests
/ sizeof *tests
};
730 main (int argc
, char *argv
[])
736 fprintf (stderr
, "exactly one argument required; use --help for help\n");
739 else if (!strcmp (argv
[1], "--help"))
741 printf ("%s: test balanced tree\n"
742 "usage: %s TEST-NAME\n"
743 "where TEST-NAME is one of the following:\n",
745 for (i
= 0; i
< N_TESTS
; i
++)
746 printf (" %s\n %s\n", tests
[i
].name
, tests
[i
].description
);
751 for (i
= 0; i
< N_TESTS
; i
++)
752 if (!strcmp (argv
[1], tests
[i
].name
))
754 tests
[i
].function ();
758 fprintf (stderr
, "unknown test %s; use --help for help\n", argv
[1]);