static AvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(UWord,UWord) ) { if (kCmp) { /* Boxed comparisons */ Word cmpresS; while (True) { if (t == NULL) return NULL; cmpresS = kCmp(t->key, k); if (cmpresS > 0) t = t->child[0]; else if (cmpresS < 0) t = t->child[1]; else return t; } } else { /* Unboxed comparisons */ Word cmpresS; /* signed */ UWord cmpresU; /* unsigned */ while (True) { if (t == NULL) return NULL; /* unlikely ==> predictable */ cmpresS = cmp_unsigned_Words( (UWord)t->key, (UWord)k ); if (cmpresS == 0) return t; /* unlikely ==> predictable */ cmpresU = (UWord)cmpresS; cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1); t = t->child[cmpresU]; } } }
static AvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(Word,Word) ) { Word cmpres; while (True) { if (t == NULL) return NULL; cmpres = kCmp(t->key, k); if (cmpres > 0) t = t->left; else if (cmpres < 0) t = t->right; else return t; } }
static Bool avl_find_bounds ( AvlNode* t, /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP, /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP, UWord minKey, UWord minVal, UWord maxKey, UWord maxVal, UWord key, Word(*kCmp)(UWord,UWord) ) { UWord kLowerBound = minKey; UWord vLowerBound = minVal; UWord kUpperBound = maxKey; UWord vUpperBound = maxVal; while (t) { Word cmpresS = kCmp ? kCmp(t->key, key) : cmp_unsigned_Words(t->key, key); if (cmpresS < 0) { kLowerBound = t->key; vLowerBound = t->val; t = t->child[1]; continue; } if (cmpresS > 0) { kUpperBound = t->key; vUpperBound = t->val; t = t->child[0]; continue; } /* We should never get here. If we do, it means the given key is actually present in the tree, which means the original call was invalid -- an error on the caller's part, and we cannot give any meaningful values for the bounds. (Well, maybe we could, but we're not gonna. Ner!) */ return False; } if (kMinP) *kMinP = kLowerBound; if (vMinP) *vMinP = vLowerBound; if (kMaxP) *kMaxP = kUpperBound; if (vMaxP) *vMaxP = vUpperBound; return True; }
/* Remove an element a from the AVL tree t. a must be part of the tree. Returns True if the depth of the tree has shrunk. */ static Bool avl_remove_wrk ( AvlNode** rootp, AvlNode* a, Word(*kCmp)(Word,Word) ) { Bool ch; Word cmpres = kCmp( (*rootp)->key, a->key ); if (cmpres > 0) { /* remove from the left subtree */ AvlNode* left_subtree = (*rootp)->left; assert(left_subtree); ch = avl_remove_wrk(&left_subtree, a, kCmp); (*rootp)->left=left_subtree; if (ch) { switch ((*rootp)->balance++) { case -1: return True; case 0: return False; case 1: break; default: assert(0); } switch ((*rootp)->right->balance) { case 0: avl_swl( rootp ); (*rootp)->balance = -1; (*rootp)->left->balance = 1; return False; case 1: avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->left->balance = 0; return -1; case -1: break; default: assert(0); } avl_swr( &((*rootp)->right) ); avl_swl( rootp ); avl_nasty( *rootp ); return True; } } else if (cmpres < 0) { /* remove from the right subtree */ AvlNode* right_subtree = (*rootp)->right; assert(right_subtree); ch = avl_remove_wrk(&right_subtree, a, kCmp); (*rootp)->right = right_subtree; if (ch) { switch ((*rootp)->balance--) { case 1: return True; case 0: return False; case -1: break; default: assert(0); } switch ((*rootp)->left->balance) { case 0: avl_swr( rootp ); (*rootp)->balance = 1; (*rootp)->right->balance = -1; return False; case -1: avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->right->balance = 0; return True; case 1: break; default: assert(0); } avl_swl( &((*rootp)->left) ); avl_swr( rootp ); avl_nasty( *rootp ); return True; } } else { assert(cmpres == 0); assert((*rootp)==a); return avl_removeroot_wrk(rootp, kCmp); } return 0; }
/* Insert element a into the AVL tree t. Returns True if the depth of the tree has grown. If element with that key is already present, just copy a->val to existing node, first returning old ->val field of existing node in *oldV, so that the caller can finalize it however it wants. */ static Bool avl_insert_wrk ( AvlNode** rootp, /*OUT*/MaybeWord* oldV, AvlNode* a, Word (*kCmp)(Word,Word) ) { Word cmpres; /* initialize */ a->left = 0; a->right = 0; a->balance = 0; oldV->b = False; /* insert into an empty tree? */ if (!(*rootp)) { (*rootp) = a; return True; } cmpres = kCmp( (*rootp)->key, a->key ); if (cmpres > 0) { /* insert into the left subtree */ if ((*rootp)->left) { AvlNode* left_subtree = (*rootp)->left; if (avl_insert_wrk(&left_subtree, oldV, a, kCmp)) { switch ((*rootp)->balance--) { case 1: return False; case 0: return True; case -1: break; default: assert(0); } if ((*rootp)->left->balance < 0) { avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->right->balance = 0; } else { avl_swl( &((*rootp)->left) ); avl_swr( rootp ); avl_nasty( *rootp ); } } else { (*rootp)->left = left_subtree; } return False; } else { (*rootp)->left = a; if ((*rootp)->balance--) return False; return True; } assert(0);/*NOTREACHED*/ } else if (cmpres < 0) { /* insert into the right subtree */ if ((*rootp)->right) { AvlNode* right_subtree = (*rootp)->right; if (avl_insert_wrk(&right_subtree, oldV, a, kCmp)) { switch((*rootp)->balance++) { case -1: return False; case 0: return True; case 1: break; default: assert(0); } if ((*rootp)->right->balance > 0) { avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->left->balance = 0; } else { avl_swr( &((*rootp)->right) ); avl_swl( rootp ); avl_nasty( *rootp ); } } else { (*rootp)->right = right_subtree; } return False; } else { (*rootp)->right = a; if ((*rootp)->balance++) return False; return True; } assert(0);/*NOTREACHED*/ } else { /* cmpres == 0, a duplicate - replace the val, but don't incorporate the node in the tree */ oldV->b = True; oldV->w = (*rootp)->val; (*rootp)->val = a->val; return False; } }
/* Remove an element a from the AVL tree t. a must be part of the tree. Returns True if the depth of the tree has shrunk. */ static Bool avl_remove_wrk ( AvlNode** rootp, AvlNode* a, Word(*kCmp)(UWord,UWord) ) { Bool ch; Word cmpres; cmpres = kCmp ? /*boxed*/ kCmp( (*rootp)->key, a->key ) : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key, (UWord)a->key ); if (cmpres > 0){ /* remove from the left subtree */ AvlNode* left_subtree = (*rootp)->child[0]; tl_assert(left_subtree); ch = avl_remove_wrk(&left_subtree, a, kCmp); (*rootp)->child[0]=left_subtree; if (ch) { switch ((*rootp)->balance++) { case -1: return True; case 0: return False; case 1: break; default: tl_assert(0); } switch ((*rootp)->child[1]->balance) { case 0: avl_swl( rootp ); (*rootp)->balance = -1; (*rootp)->child[0]->balance = 1; return False; case 1: avl_swl( rootp ); (*rootp)->balance = 0; (*rootp)->child[0]->balance = 0; return True; case -1: break; default: tl_assert(0); } avl_swr( &((*rootp)->child[1]) ); avl_swl( rootp ); avl_nasty( *rootp ); return True; } } else if (cmpres < 0) { /* remove from the right subtree */ AvlNode* right_subtree = (*rootp)->child[1]; tl_assert(right_subtree); ch = avl_remove_wrk(&right_subtree, a, kCmp); (*rootp)->child[1] = right_subtree; if (ch) { switch ((*rootp)->balance--) { case 1: return True; case 0: return False; case -1: break; default: tl_assert(0); } switch ((*rootp)->child[0]->balance) { case 0: avl_swr( rootp ); (*rootp)->balance = 1; (*rootp)->child[1]->balance = -1; return False; case -1: avl_swr( rootp ); (*rootp)->balance = 0; (*rootp)->child[1]->balance = 0; return True; case 1: break; default: tl_assert(0); } avl_swl( &((*rootp)->child[0]) ); avl_swr( rootp ); avl_nasty( *rootp ); return True; } } else { tl_assert(cmpres == 0); tl_assert((*rootp)==a); return avl_removeroot_wrk(rootp, kCmp); } return 0; }