From 48f51861d35c43713759d600508fd498fb2682a7 Mon Sep 17 00:00:00 2001 From: Tim Prins Date: Tue, 22 Jun 2004 20:52:18 +0000 Subject: [PATCH] Adding a new class which is a red black tree -reviewed by Tim adding a small test program for the tree This commit was SVN r1437. --- src/class/Makefile.am | 6 +- src/class/ompi_rb_tree.c | 547 ++++++++++++++++++++++++++++++++++++++ src/class/ompi_rb_tree.h | 186 +++++++++++++ test/class/Makefile.am | 17 +- test/class/ompi_rb_tree.c | 169 ++++++++++++ 5 files changed, 921 insertions(+), 4 deletions(-) create mode 100644 src/class/ompi_rb_tree.c create mode 100644 src/class/ompi_rb_tree.h create mode 100644 test/class/ompi_rb_tree.c diff --git a/src/class/Makefile.am b/src/class/Makefile.am index babd23e245..0f6916adc4 100644 --- a/src/class/Makefile.am +++ b/src/class/Makefile.am @@ -16,7 +16,8 @@ headers = \ ompi_list.h \ ompi_object.h \ ompi_pointer_array.h \ - ompi_value_array.h + ompi_value_array.h \ + ompi_rb_tree.h liblfc_la_SOURCES = \ $(headers) \ @@ -26,7 +27,8 @@ liblfc_la_SOURCES = \ ompi_object.c \ ompi_pointer_array.c \ ompi_bitmap.c \ - ompi_value_array.c + ompi_value_array.c \ + ompi_rb_tree.c # Conditionally install the header files diff --git a/src/class/ompi_rb_tree.c b/src/class/ompi_rb_tree.c new file mode 100644 index 0000000000..0e461cfca6 --- /dev/null +++ b/src/class/ompi_rb_tree.c @@ -0,0 +1,547 @@ +/* + * $HEADER$ + */ +/* + * @file + */ + +#include "class/ompi_rb_tree.h" + +/* declare the instance of the classes */ +OBJ_CLASS_INSTANCE(ompi_rb_tree_node_t, ompi_list_item_t, NULL, NULL); +OBJ_CLASS_INSTANCE(ompi_rb_tree_t, ompi_object_t, ompi_rb_tree_construct, + ompi_rb_tree_destruct); + +/* Private functions */ +static void btree_insert(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * node); +static void btree_delete_fixup(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x); +static ompi_rb_tree_node_t * btree_successor(ompi_rb_tree_t * tree, + ompi_rb_tree_node_t * node); +static ompi_rb_tree_node_t * ompi_rb_tree_find_node(ompi_rb_tree_t *tree, void *key); +static void left_rotate(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x); +static void right_rotate(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x); +static void inorder_destroy(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * node); +static void inorder_traversal(ompi_rb_tree_t *tree, + ompi_rb_tree_condition_fn_t cond, + ompi_rb_tree_action_fn_t action, + ompi_rb_tree_node_t * node); + + + +/* constructor */ +void ompi_rb_tree_construct(ompi_object_t * object) +{ + ompi_rb_tree_t * tree = (ompi_rb_tree_t *) object; + OBJ_CONSTRUCT(&(tree->free_list), ompi_free_list_t); + ompi_free_list_init(&(tree->free_list), sizeof(ompi_rb_tree_node_t), + OBJ_CLASS(ompi_rb_tree_node_t), + 0, -1 , 128, NULL); +} + +/* the destructor function */ +void ompi_rb_tree_destruct(ompi_object_t * object) +{ + ompi_rb_tree_destroy((ompi_rb_tree_t *) object); + OBJ_DESTRUCT(&(((ompi_rb_tree_t *)object)->free_list)); + return; +} + +/* Create the tree */ +int ompi_rb_tree_init(ompi_rb_tree_t * tree, + ompi_rb_tree_comp_fn_t comp) +{ + int rc; + + ompi_list_item_t * node; + /* we need to get memory for the root pointer from the free list */ + OMPI_FREE_LIST_GET(&(tree->free_list), node, rc); + tree->root_ptr = (ompi_rb_tree_node_t *) node; + if (OMPI_SUCCESS != rc) { + return rc; + } + + OMPI_FREE_LIST_GET(&(tree->free_list), node, rc); + if (OMPI_SUCCESS != rc) { + return rc; + } + tree->nill = (ompi_rb_tree_node_t *) node; + /* initialize tree->nill */ + tree->nill->color = BLACK; + tree->nill->left = tree->nill; + tree->nill->right = tree->nill; + tree->nill->parent = tree->nill; + + /* initialize the 'root' pointer */ + tree->root_ptr->left = tree->nill; + tree->root_ptr->right = tree->nill; + tree->root_ptr->parent = tree->nill; + tree->root_ptr->color = BLACK; + + tree->comp = comp; + + /* set the tree size to zero */ + tree->tree_size = 0; + + return(OMPI_SUCCESS); +} + + +/* This inserts a node into the tree based on the passed values. */ +int ompi_rb_tree_insert(ompi_rb_tree_t *tree, void * key, void * value) +{ + ompi_rb_tree_node_t * y; + ompi_rb_tree_node_t * node; + ompi_list_item_t * item; + int rc; + + /* get the memory for a node */ + OMPI_FREE_LIST_GET(&(tree->free_list), item, rc); + if (OMPI_SUCCESS != rc) { + return rc; + } + node = (ompi_rb_tree_node_t *) item; + /* insert the data into the node */ + node->key = key; + node->value = value; + + /* insert the node into the tree */ + btree_insert(tree, node); + + /*do the rotations */ + /* usually one would have to check for NULL, but because of the sentinal, + * we don't have to */ + while (node->parent->color == RED) { + if (node->parent == node->parent->parent->left) { + y = node->parent->parent->right; + if (y->color == RED) { + node->parent->color = BLACK; + y->color = BLACK; + node->parent->parent->color = RED; + node = node->parent->parent; + } else { + if (node == node->parent->right) { + node = node->parent; + left_rotate(tree, node); + } + node->parent->color = BLACK; + node->parent->parent->color = RED; + right_rotate(tree, node->parent->parent); + } + } else { + y = node->parent->parent->left; + if (y->color == RED) { + node->parent->color = BLACK; + y->color = BLACK; + node->parent->parent->color = RED; + node = node->parent->parent; + } else { + if (node == node->parent->left) { + node = node->parent; + right_rotate(tree, node); + } + node->parent->color = BLACK; + node->parent->parent->color = RED; + left_rotate(tree, node->parent->parent); + } + } + } + /* after the rotations the root is black */ + tree->root_ptr->left->color = BLACK; + return OMPI_SUCCESS; +} + + +/* Finds the node in the tree based on the key */ +void * ompi_rb_tree_find(ompi_rb_tree_t *tree, void *key) +{ + ompi_rb_tree_node_t * node; + int compvalue; + + node = tree->root_ptr->left; + while (node != tree->nill) { + compvalue = tree->comp(key, node->key); + /* if the result of the comparison function is 0, we found it */ + if (compvalue == 0) { + return(node->value); + } + /* else if it is less than 0, go left, else right */ + (compvalue < 0) ? (node = node->left) : (node = node->right); + } + /* if we didn't find anything, return NULL */ + return(NULL); +} + +/* Finds the node in the tree based on the key and returns a pointer + * to the node. This is a bit a code duplication, but this has to be fast + * so we go ahead with the duplication */ +ompi_rb_tree_node_t * ompi_rb_tree_find_node(ompi_rb_tree_t *tree, void *key) +{ + ompi_rb_tree_node_t * node; + int compvalue; + + node = tree->root_ptr->left; + while (node != tree->nill) { + compvalue = tree->comp(key, node->key); + /* if the result of the comparison function is 0, we found it */ + if (compvalue == 0) { + return(node); + } + /* else if it is less than 0, go left, else right */ + (compvalue < 0) ? (node = node->left) : (node = node->right); + } + /* if we didn't find anything, return NULL */ + return(NULL); +} + +/* Delete a node from the tree based on the key */ +int ompi_rb_tree_delete(ompi_rb_tree_t *tree, void *key) +{ + ompi_rb_tree_node_t * p; + ompi_rb_tree_node_t * todelete; + ompi_rb_tree_node_t * y; + ompi_list_item_t * item; + + p = ompi_rb_tree_find_node(tree, key); + if (NULL == p) { + return(OMPI_ERR_NOT_FOUND); + } + if ((p->left == tree->nill) || (p->right == tree->nill)) { + todelete = p; + } else { + todelete = btree_successor(tree, p); + } + + if (todelete->left == tree->nill) { + y = todelete->right; + } else { + y = todelete->left; + } + + y->parent = todelete->parent; + + if (y->parent == tree->root_ptr) { + tree->root_ptr->left = y; + } else { + if (todelete == todelete->parent->left) { + todelete->parent->left = y; + } else { + todelete->parent->right = y; + } + } + + if (todelete != p) { + p->key = todelete->key; + p->value = todelete->value; + } + + if (todelete->color == BLACK) { + btree_delete_fixup(tree, y); + } + item = (ompi_list_item_t *) todelete; + OMPI_FREE_LIST_RETURN(&(tree->free_list), item); + --tree->tree_size; + return(OMPI_SUCCESS); +} + + +/* Destroy the hashmap */ +int ompi_rb_tree_destroy(ompi_rb_tree_t *tree) +{ + ompi_list_item_t * item; + /* Recursive inorder traversal for delete */ + + inorder_destroy(tree, tree->root_ptr); + /* Now free the root -- root does not get free'd in the above + * inorder destroy */ + item = (ompi_list_item_t *) tree->root_ptr; + OMPI_FREE_LIST_RETURN(&(tree->free_list), item); + --tree->tree_size; + + /* free the tree->nill node */ + item = (ompi_list_item_t *) tree->nill; + OMPI_FREE_LIST_RETURN(&(tree->free_list), item); + return(OMPI_SUCCESS); +} + + +/* Find the next inorder successor of a node */ + +ompi_rb_tree_node_t * btree_successor(ompi_rb_tree_t * tree, ompi_rb_tree_node_t * node) +{ + ompi_rb_tree_node_t * p; + + if (node->right == tree->nill) { + p = node->parent; + while (node == p->right) { + node = p; + p = p->parent; + } + if(p == tree->root_ptr) { + return(tree->nill); + } + return p; + } + + p = node->right; + while(p->left != tree->nill) { + p = p->left; + } + return p; +} + + +/* Insert an element in the normal binary search tree fashion */ +/* this function goes through the tree and finds the leaf where + * the node will be inserted */ +void btree_insert(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * node) +{ + ompi_rb_tree_node_t * parent = tree->root_ptr; + ompi_rb_tree_node_t * n = parent->left; /* the real root of the tree */ + + /* set up initial values for the node */ + node->color = RED; + node->parent = NULL; + node->left = tree->nill; + node->right = tree->nill; + + /* find the leaf where we will insert the node */ + while (n != tree->nill) { + parent = n; + (tree->comp(node->key, n->key) <= 0) ? (n = n->left) : (n = n->right); + } + + /* place it on either the left or the right */ + if((parent == tree->root_ptr) || (tree->comp(node->key, parent->key) <= 0)) { + parent->left = node; + } else { + parent->right = node; + } + + /* set its parent and children */ + node->parent = parent; + node->left = tree->nill; + node->right = tree->nill; + ++(tree->tree_size); + return; +} + +/* Fixup the balance of the btree after deletion */ +void btree_delete_fixup(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x) +{ + ompi_rb_tree_node_t * w; + ompi_rb_tree_node_t * root = tree->root_ptr->left; + while ((x != root) && (x->color == BLACK)) { + if (x == x->parent->left) { + w = x->parent->right; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + left_rotate(tree, x->parent); + w = x->parent->right; + } + if ((w->left->color == BLACK) && (w->right->color == BLACK)) { + w->color = RED; + x = x->parent; + } else { + if (w->right->color == BLACK) { + w->left->color = BLACK; + w->color = RED; + right_rotate(tree, w); + w = x->parent->right; + } + w->color = x->parent->color; + x->parent->color = BLACK; + w->right->color = BLACK; + left_rotate(tree, x->parent); + x = root; + } + } else { /* right */ + + w = x->parent->left; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + right_rotate(tree, x->parent); + w = x->parent->left; + } + if ((w->right->color == BLACK) && (w->left->color == BLACK)) { + w->color = RED; + x = x->parent; + } else { + if (w->left->color == BLACK) { + w->right->color = BLACK; + w->color = RED; + left_rotate(tree, w); + w = x->parent->left; + } + w->color = x->parent->color; + x->parent->color = BLACK; + w->left->color = BLACK; + right_rotate(tree, x->parent); + x = root; + } + } + } + + x->color = BLACK; + return; +} + + +/* Free the nodes in inorder fashion */ + +void +inorder_destroy(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * node) +{ + ompi_list_item_t * item; + + if (node == tree->nill) { + return; + } + + inorder_destroy(tree, node->left); + + --tree->tree_size; + + if (node->left != tree->nill) { + item = (ompi_list_item_t *) node->left; + --tree->tree_size; + OMPI_FREE_LIST_RETURN(&(tree->free_list), item); + } + + inorder_destroy(tree, node->right); + if (node->right != tree->nill) { + item = (ompi_list_item_t *) node->right; + --tree->tree_size; + OMPI_FREE_LIST_RETURN(&(tree->free_list), item); + } +} + +/* Try to access all the elements of the hashmap conditionally */ + +int ompi_rb_tree_traverse(ompi_rb_tree_t *tree, + ompi_rb_tree_condition_fn_t cond, + ompi_rb_tree_action_fn_t action) +{ + if ((cond == NULL) || (action == NULL)) { + return(OMPI_ERROR); + } + + inorder_traversal(tree, cond, action, tree->root_ptr->left); + + return(OMPI_SUCCESS); +} + + +static void inorder_traversal(ompi_rb_tree_t *tree, + ompi_rb_tree_condition_fn_t cond, + ompi_rb_tree_action_fn_t action, + ompi_rb_tree_node_t * node) +{ + if (node == tree->nill) { + return; + } + + inorder_traversal(tree, cond, action, node->left); + + if (cond(node->value)) { + action(node->key, node->value); + } + + inorder_traversal(tree, cond, action, node->right); +} + +/* Left rotate the tree */ +/* basically what we want to do is to make x be the left child + * of its right child */ +void left_rotate(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x) +{ + ompi_rb_tree_node_t * y; + + y = x->right; + /* make the left child of y's parent be x if it is not the sentinal node*/ + if (y->left != tree->nill) { + y->left->parent=x; + } + + /* normlly we would have to check to see if we are at the root. + * however, the root sentinal takes care of it for us */ + if (x == x->parent->left) { + x->parent->left = y; + } else { + x->parent->right = y; + } + /* the old parent of x is now y's parent */ + y->parent = x->parent; + /* x's parent is y */ + x->parent = y; + x->right = y->left; + y->left = x; + + return; +} + + +/* Right rotate the tree */ +/* basically what we want to do is to make x be the right child + * of its left child */ +void right_rotate(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * x) +{ + ompi_rb_tree_node_t * y; + + y = x->left; + + if(y->right != tree->nill) { + y->right->parent = y; + } + + if (x == x->parent->left) { + x->parent->left = y; + } else { + x->parent->right = y; + } + + y->parent = x->parent; + x->parent = y; + x->left = y->right; + y->right = x; + + return; +} + + +/* returns the size of the tree */ +int ompi_rb_tree_size(ompi_rb_tree_t *tree) +{ + return(tree->tree_size); +} + +/* below are a couple of debugging functions */ +#if 0 +#include +static void inorder(ompi_rb_tree_t * tree, ompi_rb_tree_node_t * node); +static void print_inorder(ompi_rb_tree_t * tree); + +void inorder(ompi_rb_tree_t * tree, ompi_rb_tree_node_t * node) +{ + static int level = 0; + if (node == tree->nill) { + printf("nill\n"); + return; + } + level++; + inorder(tree, node->left); + level--; + printf("%d, level: %d\n", *((int *)node->value), level); + level++; + inorder(tree, node->right); + level--; +} + + +void print_inorder(ompi_rb_tree_t *tree) +{ + inorder(tree, tree->root_ptr->left); +} + +#endif diff --git a/src/class/ompi_rb_tree.h b/src/class/ompi_rb_tree.h new file mode 100644 index 0000000000..78b58f219c --- /dev/null +++ b/src/class/ompi_rb_tree.h @@ -0,0 +1,186 @@ +/* + * $HEADER$ + * + */ + +/** @file + * + * A red black tree + */ + +#ifndef OMPI_RB_TREE_H +#define OMPI_RB_TREE_H + +#include +#include "include/constants.h" +#include "class/ompi_object.h" +#include "class/ompi_free_list.h" + +/* + * Data structures and datatypes + */ + +/** + * red and black enum + */ +typedef enum {RED, BLACK} ompi_rb_tree_nodecolor_t; + +/** + * node data structure + */ +struct ompi_rb_tree_node_t +{ + ompi_list_item_t super; /**< the parent class */ + ompi_rb_tree_nodecolor_t color; /**< the node color */ + struct ompi_rb_tree_node_t * parent;/**< the parent node, can be NULL */ + struct ompi_rb_tree_node_t * left; /**< the left child - can be nill */ + struct ompi_rb_tree_node_t * right; /**< the right child - can be nill */ + void *key; /**< a pointer to the key */ + void *value; /**< a pointer to the value */ +}; +typedef struct ompi_rb_tree_node_t ompi_rb_tree_node_t; + +/** + * the compare function typedef. This function is used to compare 2 nodes. + */ +typedef int (*ompi_rb_tree_comp_fn_t)(void *key1, void *key2); + +/** + * the data structure that holds all the needed information about the tree. + */ +struct ompi_rb_tree_t { + ompi_object_t parent; /**< the parent class */ + /* this root pointer doesn't actually point to the root of the tree. + * rather, it points to a sentinal node who's left branch is the real + * root of the tree. This is done to eliminate special cases */ + ompi_rb_tree_node_t * root_ptr;/**< a pointer to the root of the tree */ + ompi_rb_tree_node_t * nill; /**< the nill sentinal node */ + ompi_rb_tree_comp_fn_t comp; /**< the compare function */ + ompi_free_list_t free_list; /**< the free list to get the memory from */ + size_t tree_size; /**< the size of the tree */ +}; +typedef struct ompi_rb_tree_t ompi_rb_tree_t; + +/** declare the tree node as a class */ +OBJ_CLASS_DECLARATION(ompi_rb_tree_node_t); +/** declare the tree as a class */ +OBJ_CLASS_DECLARATION(ompi_rb_tree_t); + +/* Function pointers for map traversal function */ +/** + * this function is used for the ompi_rb_tree_traverse function. + * it is passed a pointer to the value for each node and, if it returns + * a one, the action function is called on that node. Otherwise, the node is ignored. + */ +typedef int (*ompi_rb_tree_condition_fn_t)(void *); +/** + * this function is uused for the user to perform any action on the passed + * values. The first argument is the key and the second is the value. + * note that this function SHOULD NOT modify the keys, as that would + * mess up the tree. + */ +typedef void (*ompi_rb_tree_action_fn_t)(void *, void *); + +/* + * Public function protoypes + */ + +/** + * the construct function. creates the free list to get the nodes from + * + * @param object the tree that is to be used + * + * @retval NONE + */ +void ompi_rb_tree_construct(ompi_object_t * object); + +/** + * the destruct function. tries to free the tree and destroys the free list + * + * @param object the tree object + */ +void ompi_rb_tree_destruct(ompi_object_t * object); + +/** + * the function creates a new tree + * + * @param tree a pointer to an allocated area of memory for the main + * tree data structure. + * @param comp a pointer to the function to use for comaparing 2 nodes + * + * @retval OMPI_SUCCESS if it is successful + * @retval OMPI_ERR_TEMP_OUT_OF_RESOURCE if unsuccessful + */ +int ompi_rb_tree_init(ompi_rb_tree_t * tree, ompi_rb_tree_comp_fn_t comp); + + +/** + * inserts a node into the tree + * + * @param tree a pointer to the tree data structure + * @param key the key for the node + * @param value the value for the node + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERR_TEMP_OUT_OF_RESOURCE if unsuccessful + */ +int ompi_rb_tree_insert(ompi_rb_tree_t *tree, void * key, void * value); + +/** + * finds a value in the tree based on the passed key + * + * @param tree a pointer to the tree data structure + * @param key a pointer to the key + * + * @retval pointer to the value if found + * @retval NULL if not found + */ +void * ompi_rb_tree_find(ompi_rb_tree_t *tree, void *key); + +/** + * deletes a node based on its key + * + * @param tree a pointer to the tree data structure + * @param key a pointer to the key + * + * @retval OMPI_SUCCESS if the node is found and deleted + * @retval OMPI_ERR_NOT_FOUND if the node is not found + */ +int ompi_rb_tree_delete(ompi_rb_tree_t *tree, void *key); + +/** + * frees all the nodes on the tree + * + * @param tree a pointer to the tree data structure + * + * @retval OMPI_SUCCESS + */ +int ompi_rb_tree_destroy(ompi_rb_tree_t *tree); + +/** + * traverses the entire tree, performing the cond function on each of the + * values and if it returns one it performs the action function on the values + * + * @param tree a pointer to the tree + * @param cond a pointer to the condition function + * @param action a pointer to the action function + * + * @retval OMPI_SUCCESS + * @retval OMPI_FAILURE if there is an error + */ +int ompi_rb_tree_traverse(ompi_rb_tree_t *tree, + ompi_rb_tree_condition_fn_t cond, + ompi_rb_tree_action_fn_t action); + +/** + * returns the size of the tree + * + * @param tree a pointer to the tree data structure + * + * @retval int the nuber of items on the tree + */ +int ompi_rb_tree_size(ompi_rb_tree_t *tree); + + +#endif /* OMPI_RB_TREE_H */ + diff --git a/test/class/Makefile.am b/test/class/Makefile.am index 93f35ec5f8..1d080d4bc9 100644 --- a/test/class/Makefile.am +++ b/test/class/Makefile.am @@ -11,7 +11,8 @@ noinst_PROGRAMS = \ ompi_hash_table \ ompi_list \ ompi_value_array \ - ompi_pointer_array + ompi_pointer_array \ + ompi_rb_tree ompi_bitmap_SOURCES = ompi_bitmap.c ompi_bitmap_LDADD = \ @@ -76,4 +77,16 @@ ompi_value_array_LDADD = \ $(top_builddir)/test/support/libsupport.la ompi_value_array_DEPENDENCIES = $(ompi_value_array_LDADD) - +ompi_rb_tree_SOURCES = ompi_rb_tree.c +ompi_rb_tree_LDADD = \ + $(top_builddir)/test/support/libsupport.la \ + $(top_builddir)/src/class/ompi_free_list.lo \ + $(top_builddir)/src/class/ompi_rb_tree.lo \ + $(top_builddir)/src/class/ompi_object.lo \ + $(top_builddir)/src/class/ompi_list.lo \ + $(top_builddir)/src/threads/mutex.lo \ + $(top_builddir)/src/threads/mutex_pthread.lo \ + $(top_builddir)/src/threads/mutex_spinlock.lo \ + $(top_builddir)/src/util/output.lo \ + $(top_builddir)/src/util/malloc.lo +ompi_rb_tree_DEPENDENCIES = $(ompi_rb_tree_LDADD) diff --git a/test/class/ompi_rb_tree.c b/test/class/ompi_rb_tree.c new file mode 100644 index 0000000000..5b8261281b --- /dev/null +++ b/test/class/ompi_rb_tree.c @@ -0,0 +1,169 @@ +/* + * $HEADER$ + */ + +#include +#include +#include "support.h" +#include "class/ompi_rb_tree.h" + +int keys[] = { + 0, 1, 2, 3, 4, 5, 6, 7 +}; + +int values[] = { + 10, 11, 12, 13, 14, 15, 16, 17 +}; + +int comp_fn(void * ele1, void * ele2); + +void test1(void); + +int comp_fn(void * ele1, void * ele2) +{ + if(*((int *) ele1) > *((int *) ele2)) { + return(1); + } + if(*((int *) ele1) < *((int *) ele2)) { + return(-1); + } + return(0); +} + +void test1(void) +{ + ompi_rb_tree_t tree; + int rc; + void * result; + + OBJ_CONSTRUCT(&tree, ompi_rb_tree_t); + rc = ompi_rb_tree_init(&tree, comp_fn); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly initialize the tree"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[0], &values[0]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[0]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[0], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[1], &values[1]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[1]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[1], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[2], &values[2]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[2]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[2], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[3], &values[3]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[3]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[3], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[4], &values[4]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[4]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[4], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[5], &values[5]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[5]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[5], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[6], &values[6]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[6]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[6], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_insert(&tree, &keys[7], &values[7]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly insert a new node"); + } + result = ompi_rb_tree_find(&tree, &keys[7]); + if(NULL == result) { + test_failure("lookup returned null!"); + } + if(!test_verify_int(values[7], *((int *) result))) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_size(&tree); + if(!test_verify_int(8, rc)) { + test_failure("failed to properly insert a new node"); + } + + rc = ompi_rb_tree_delete(&tree, &keys[0]); + if(!test_verify_int(OMPI_SUCCESS, rc)) { + test_failure("failed to properly delete a node"); + } + result = ompi_rb_tree_find(&tree, &keys[0]); + if(NULL != result) { + test_failure("lookup returned a value instead of null!"); + } else { + test_success(); + } + + OBJ_DESTRUCT(&tree); +} + + +int main(int argc, char **argv) +{ + /* local variables */ + test_init("ompi_rb_tree_t"); + + test1(); + + return test_finalize(); +}