1b411202f9ff33a587558e2e836626bc7eb9db183sewardj 2b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--------------------------------------------------------------------*/ 3b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--- An AVL tree based finite map for word keys and word values. ---*/ 4b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--- Inspired by Haskell's "FiniteMap" library. ---*/ 5896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj/*--- m_wordfm.c ---*/ 6b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--------------------------------------------------------------------*/ 7b411202f9ff33a587558e2e836626bc7eb9db183sewardj 8b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* 9896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj This file is part of Valgrind, a dynamic binary instrumentation 10896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj framework. 11b411202f9ff33a587558e2e836626bc7eb9db183sewardj 12b3a1e4bffbdbbf38304f216af405009868f43628sewardj Copyright (C) 2007-2015 Julian Seward 13b411202f9ff33a587558e2e836626bc7eb9db183sewardj jseward@acm.org 14b411202f9ff33a587558e2e836626bc7eb9db183sewardj 15b411202f9ff33a587558e2e836626bc7eb9db183sewardj This code is based on previous work by Nicholas Nethercote 16b411202f9ff33a587558e2e836626bc7eb9db183sewardj (coregrind/m_oset.c) which is 17b411202f9ff33a587558e2e836626bc7eb9db183sewardj 18b3a1e4bffbdbbf38304f216af405009868f43628sewardj Copyright (C) 2005-2015 Nicholas Nethercote 19b411202f9ff33a587558e2e836626bc7eb9db183sewardj njn@valgrind.org 20b411202f9ff33a587558e2e836626bc7eb9db183sewardj 21b411202f9ff33a587558e2e836626bc7eb9db183sewardj which in turn was derived partially from: 22b411202f9ff33a587558e2e836626bc7eb9db183sewardj 23b411202f9ff33a587558e2e836626bc7eb9db183sewardj AVL C library 24b411202f9ff33a587558e2e836626bc7eb9db183sewardj Copyright (C) 2000,2002 Daniel Nagy 25b411202f9ff33a587558e2e836626bc7eb9db183sewardj 26b411202f9ff33a587558e2e836626bc7eb9db183sewardj This program is free software; you can redistribute it and/or 27b411202f9ff33a587558e2e836626bc7eb9db183sewardj modify it under the terms of the GNU General Public License as 28b411202f9ff33a587558e2e836626bc7eb9db183sewardj published by the Free Software Foundation; either version 2 of 29b411202f9ff33a587558e2e836626bc7eb9db183sewardj the License, or (at your option) any later version. 30b411202f9ff33a587558e2e836626bc7eb9db183sewardj [...] 31b411202f9ff33a587558e2e836626bc7eb9db183sewardj 32b411202f9ff33a587558e2e836626bc7eb9db183sewardj (taken from libavl-0.4/debian/copyright) 33b411202f9ff33a587558e2e836626bc7eb9db183sewardj 34b411202f9ff33a587558e2e836626bc7eb9db183sewardj This program is free software; you can redistribute it and/or 35b411202f9ff33a587558e2e836626bc7eb9db183sewardj modify it under the terms of the GNU General Public License as 36b411202f9ff33a587558e2e836626bc7eb9db183sewardj published by the Free Software Foundation; either version 2 of the 37b411202f9ff33a587558e2e836626bc7eb9db183sewardj License, or (at your option) any later version. 38b411202f9ff33a587558e2e836626bc7eb9db183sewardj 39b411202f9ff33a587558e2e836626bc7eb9db183sewardj This program is distributed in the hope that it will be useful, but 40b411202f9ff33a587558e2e836626bc7eb9db183sewardj WITHOUT ANY WARRANTY; without even the implied warranty of 41b411202f9ff33a587558e2e836626bc7eb9db183sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42b411202f9ff33a587558e2e836626bc7eb9db183sewardj General Public License for more details. 43b411202f9ff33a587558e2e836626bc7eb9db183sewardj 44b411202f9ff33a587558e2e836626bc7eb9db183sewardj You should have received a copy of the GNU General Public License 45b411202f9ff33a587558e2e836626bc7eb9db183sewardj along with this program; if not, write to the Free Software 46b411202f9ff33a587558e2e836626bc7eb9db183sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 47b411202f9ff33a587558e2e836626bc7eb9db183sewardj 02111-1307, USA. 48b411202f9ff33a587558e2e836626bc7eb9db183sewardj 49b411202f9ff33a587558e2e836626bc7eb9db183sewardj The GNU General Public License is contained in the file COPYING. 50b411202f9ff33a587558e2e836626bc7eb9db183sewardj*/ 51b411202f9ff33a587558e2e836626bc7eb9db183sewardj 52896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj#include "pub_core_basics.h" 53896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj#include "pub_core_libcassert.h" 54896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj#include "pub_core_libcbase.h" 55896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj#include "pub_core_wordfm.h" /* self */ 56b411202f9ff33a587558e2e836626bc7eb9db183sewardj 57ae5137e9532a4625e54fcbf103e146815717852bsewardj 58b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 59b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- WordFM ---// 60b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- Implementation ---// 61b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 62b411202f9ff33a587558e2e836626bc7eb9db183sewardj 63b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* One element of the AVL tree */ 64b411202f9ff33a587558e2e836626bc7eb9db183sewardjtypedef 65b411202f9ff33a587558e2e836626bc7eb9db183sewardj struct _AvlNode { 66250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord key; 67250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord val; 68b411202f9ff33a587558e2e836626bc7eb9db183sewardj struct _AvlNode* child[2]; /* [0] is left subtree, [1] is right */ 69b411202f9ff33a587558e2e836626bc7eb9db183sewardj Char balance; /* do not make this unsigned */ 70b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 71b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode; 72b411202f9ff33a587558e2e836626bc7eb9db183sewardj 73b411202f9ff33a587558e2e836626bc7eb9db183sewardjtypedef 74b411202f9ff33a587558e2e836626bc7eb9db183sewardj struct { 75250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord w; 76b411202f9ff33a587558e2e836626bc7eb9db183sewardj Bool b; 77b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 78b411202f9ff33a587558e2e836626bc7eb9db183sewardj MaybeWord; 79b411202f9ff33a587558e2e836626bc7eb9db183sewardj 80b411202f9ff33a587558e2e836626bc7eb9db183sewardj#define WFM_STKMAX 32 // At most 2**32 entries can be iterated over 81b411202f9ff33a587558e2e836626bc7eb9db183sewardj 82b411202f9ff33a587558e2e836626bc7eb9db183sewardjstruct _WordFM { 83b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* root; 8454fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian void* (*alloc_nofail)( const HChar*, SizeT ); 8554fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian const HChar* cc; 86b411202f9ff33a587558e2e836626bc7eb9db183sewardj void (*dealloc)(void*); 87250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word (*kCmp)(UWord,UWord); 88b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* nodeStack[WFM_STKMAX]; // Iterator node stack 89b411202f9ff33a587558e2e836626bc7eb9db183sewardj Int numStack[WFM_STKMAX]; // Iterator num stack 90b411202f9ff33a587558e2e836626bc7eb9db183sewardj Int stackTop; // Iterator stack pointer, one past end 91b411202f9ff33a587558e2e836626bc7eb9db183sewardj}; 92b411202f9ff33a587558e2e836626bc7eb9db183sewardj 93b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* forward */ 94250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardjstatic Bool avl_removeroot_wrk(AvlNode** t, Word(*kCmp)(UWord,UWord)); 95b411202f9ff33a587558e2e836626bc7eb9db183sewardj 96b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Swing to the left. Warning: no balance maintainance. */ 97b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void avl_swl ( AvlNode** root ) 98b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 99b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* a = *root; 100b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* b = a->child[1]; 101b411202f9ff33a587558e2e836626bc7eb9db183sewardj *root = b; 102b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[1] = b->child[0]; 103b411202f9ff33a587558e2e836626bc7eb9db183sewardj b->child[0] = a; 104b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 105b411202f9ff33a587558e2e836626bc7eb9db183sewardj 106b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Swing to the right. Warning: no balance maintainance. */ 107b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void avl_swr ( AvlNode** root ) 108b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 109b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* a = *root; 110b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* b = a->child[0]; 111b411202f9ff33a587558e2e836626bc7eb9db183sewardj *root = b; 112b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[0] = b->child[1]; 113b411202f9ff33a587558e2e836626bc7eb9db183sewardj b->child[1] = a; 114b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 115b411202f9ff33a587558e2e836626bc7eb9db183sewardj 116b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Balance maintainance after especially nasty swings. */ 117b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void avl_nasty ( AvlNode* root ) 118b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 119b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch (root->balance) { 120b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: 121b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[0]->balance = 0; 122b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[1]->balance = 1; 123b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 124b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: 125b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[0]->balance = -1; 126b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[1]->balance = 0; 127b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 128b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: 129b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[0]->balance = 0; 130b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->child[1]->balance = 0; 131b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 132b411202f9ff33a587558e2e836626bc7eb9db183sewardj default: 133e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0); 134b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 135b411202f9ff33a587558e2e836626bc7eb9db183sewardj root->balance=0; 136b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 137b411202f9ff33a587558e2e836626bc7eb9db183sewardj 138b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Find size of a non-NULL tree. */ 139ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianstatic UWord size_avl_nonNull ( const AvlNode* nd ) 140b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 141b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 1 + (nd->child[0] ? size_avl_nonNull(nd->child[0]) : 0) 142b411202f9ff33a587558e2e836626bc7eb9db183sewardj + (nd->child[1] ? size_avl_nonNull(nd->child[1]) : 0); 143b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 144b411202f9ff33a587558e2e836626bc7eb9db183sewardj 145250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj/* Unsignedly compare w1 and w2. If w1 < w2, produce a negative 146250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj number; if w1 > w2 produce a positive number, and if w1 == w2 147250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj produce zero. */ 148250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardjstatic inline Word cmp_unsigned_Words ( UWord w1, UWord w2 ) { 14995e790018ed15cf1f6d656b7c7973e18a77f975asewardj if (w1 < w2) return -1; 15095e790018ed15cf1f6d656b7c7973e18a77f975asewardj if (w1 > w2) return 1; 15195e790018ed15cf1f6d656b7c7973e18a77f975asewardj return 0; 15295e790018ed15cf1f6d656b7c7973e18a77f975asewardj} 15395e790018ed15cf1f6d656b7c7973e18a77f975asewardj 154b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Insert element a into the AVL tree t. Returns True if the depth of 155b411202f9ff33a587558e2e836626bc7eb9db183sewardj the tree has grown. If element with that key is already present, 156b411202f9ff33a587558e2e836626bc7eb9db183sewardj just copy a->val to existing node, first returning old ->val field 157b411202f9ff33a587558e2e836626bc7eb9db183sewardj of existing node in *oldV, so that the caller can finalize it 158b411202f9ff33a587558e2e836626bc7eb9db183sewardj however it wants. 159b411202f9ff33a587558e2e836626bc7eb9db183sewardj*/ 160b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic 161b411202f9ff33a587558e2e836626bc7eb9db183sewardjBool avl_insert_wrk ( AvlNode** rootp, 162b411202f9ff33a587558e2e836626bc7eb9db183sewardj /*OUT*/MaybeWord* oldV, 163b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* a, 164250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word (*kCmp)(UWord,UWord) ) 165b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 166b411202f9ff33a587558e2e836626bc7eb9db183sewardj Word cmpres; 167b411202f9ff33a587558e2e836626bc7eb9db183sewardj 168b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* initialize */ 169b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[0] = 0; 170b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[1] = 0; 171b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->balance = 0; 172b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldV->b = False; 173b411202f9ff33a587558e2e836626bc7eb9db183sewardj 174b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* insert into an empty tree? */ 175b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (!(*rootp)) { 176b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp) = a; 177b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 178b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 179b411202f9ff33a587558e2e836626bc7eb9db183sewardj 180b411202f9ff33a587558e2e836626bc7eb9db183sewardj cmpres = kCmp ? /*boxed*/ kCmp( (*rootp)->key, a->key ) 181250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key, 182250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj (UWord)a->key ); 183b411202f9ff33a587558e2e836626bc7eb9db183sewardj 184b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (cmpres > 0) { 185b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* insert into the left subtree */ 186b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->child[0]) { 187b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* left_subtree = (*rootp)->child[0]; 188b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (avl_insert_wrk(&left_subtree, oldV, a, kCmp)) { 189b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch ((*rootp)->balance--) { 190b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: return False; 191b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: return True; 192b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: break; 193e2800c958044937e72eefa371c10ae47ac40e089florian default: vg_assert(0); 194b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 195b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->child[0]->balance < 0) { 196b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( rootp ); 197b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = 0; 198b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1]->balance = 0; 199b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 200b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( &((*rootp)->child[0]) ); 201b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( rootp ); 202b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_nasty( *rootp ); 203b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 204b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 205b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0] = left_subtree; 206b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 207b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 208b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 209b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0] = a; 210b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->balance--) 211b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 212b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 213b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 214e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0);/*NOTREACHED*/ 215b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 216b411202f9ff33a587558e2e836626bc7eb9db183sewardj else 217b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (cmpres < 0) { 218b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* insert into the right subtree */ 219b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->child[1]) { 220b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* right_subtree = (*rootp)->child[1]; 221b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (avl_insert_wrk(&right_subtree, oldV, a, kCmp)) { 222b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch((*rootp)->balance++){ 223b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: return False; 224b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: return True; 225b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: break; 226e2800c958044937e72eefa371c10ae47ac40e089florian default: vg_assert(0); 227b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 228b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->child[1]->balance > 0) { 229b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( rootp ); 230b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = 0; 231b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0]->balance = 0; 232b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 233b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( &((*rootp)->child[1]) ); 234b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( rootp ); 235b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_nasty( *rootp ); 236b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 237b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 238b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1] = right_subtree; 239b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 240b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 241b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 242b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1] = a; 243b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->balance++) 244b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 245b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 246b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 247e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0);/*NOTREACHED*/ 248b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 249b411202f9ff33a587558e2e836626bc7eb9db183sewardj else { 250b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* cmpres == 0, a duplicate - replace the val, but don't 251b411202f9ff33a587558e2e836626bc7eb9db183sewardj incorporate the node in the tree */ 252b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldV->b = True; 253b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldV->w = (*rootp)->val; 254b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->val = a->val; 255b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 256b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 257b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 258b411202f9ff33a587558e2e836626bc7eb9db183sewardj 259b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Remove an element a from the AVL tree t. a must be part of 260b411202f9ff33a587558e2e836626bc7eb9db183sewardj the tree. Returns True if the depth of the tree has shrunk. 261b411202f9ff33a587558e2e836626bc7eb9db183sewardj*/ 262b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic 263b411202f9ff33a587558e2e836626bc7eb9db183sewardjBool avl_remove_wrk ( AvlNode** rootp, 264b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* a, 265250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word(*kCmp)(UWord,UWord) ) 266b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 267b411202f9ff33a587558e2e836626bc7eb9db183sewardj Bool ch; 268b411202f9ff33a587558e2e836626bc7eb9db183sewardj Word cmpres; 269b411202f9ff33a587558e2e836626bc7eb9db183sewardj cmpres = kCmp ? /*boxed*/ kCmp( (*rootp)->key, a->key ) 270250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key, 271250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj (UWord)a->key ); 272b411202f9ff33a587558e2e836626bc7eb9db183sewardj 273b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (cmpres > 0){ 274b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* remove from the left subtree */ 275b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* left_subtree = (*rootp)->child[0]; 276e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(left_subtree); 277b411202f9ff33a587558e2e836626bc7eb9db183sewardj ch = avl_remove_wrk(&left_subtree, a, kCmp); 278b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0]=left_subtree; 279b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (ch) { 280b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch ((*rootp)->balance++) { 281b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: return True; 282b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: return False; 283b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: break; 284e2800c958044937e72eefa371c10ae47ac40e089florian default: vg_assert(0); 285b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 286b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch ((*rootp)->child[1]->balance) { 287b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: 288b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( rootp ); 289b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = -1; 290b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0]->balance = 1; 291b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 292b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: 293b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( rootp ); 294b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = 0; 295b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[0]->balance = 0; 296b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 297b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: 298b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 299b411202f9ff33a587558e2e836626bc7eb9db183sewardj default: 300e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0); 301b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 302b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( &((*rootp)->child[1]) ); 303b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( rootp ); 304b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_nasty( *rootp ); 305b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 306b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 307b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 308b411202f9ff33a587558e2e836626bc7eb9db183sewardj else 309b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (cmpres < 0) { 310b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* remove from the right subtree */ 311b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* right_subtree = (*rootp)->child[1]; 312e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(right_subtree); 313b411202f9ff33a587558e2e836626bc7eb9db183sewardj ch = avl_remove_wrk(&right_subtree, a, kCmp); 314b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1] = right_subtree; 315b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (ch) { 316b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch ((*rootp)->balance--) { 317b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: return True; 318b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: return False; 319b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: break; 320e2800c958044937e72eefa371c10ae47ac40e089florian default: vg_assert(0); 321b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 322b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch ((*rootp)->child[0]->balance) { 323b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 0: 324b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( rootp ); 325b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = 1; 326b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1]->balance = -1; 327b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 328b411202f9ff33a587558e2e836626bc7eb9db183sewardj case -1: 329b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( rootp ); 330b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->balance = 0; 331b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp)->child[1]->balance = 0; 332b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 333b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: 334b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 335b411202f9ff33a587558e2e836626bc7eb9db183sewardj default: 336e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0); 337b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 338b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swl( &((*rootp)->child[0]) ); 339b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_swr( rootp ); 340b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_nasty( *rootp ); 341b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 342b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 343b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 344b411202f9ff33a587558e2e836626bc7eb9db183sewardj else { 345e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(cmpres == 0); 346e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert((*rootp)==a); 347b411202f9ff33a587558e2e836626bc7eb9db183sewardj return avl_removeroot_wrk(rootp, kCmp); 348b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 349b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 0; 350b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 351b411202f9ff33a587558e2e836626bc7eb9db183sewardj 352b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Remove the root of the AVL tree *rootp. 353b411202f9ff33a587558e2e836626bc7eb9db183sewardj * Warning: dumps core if *rootp is empty 354b411202f9ff33a587558e2e836626bc7eb9db183sewardj */ 355b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic 356b411202f9ff33a587558e2e836626bc7eb9db183sewardjBool avl_removeroot_wrk ( AvlNode** rootp, 357250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word(*kCmp)(UWord,UWord) ) 358b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 359b411202f9ff33a587558e2e836626bc7eb9db183sewardj Bool ch; 360b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* a; 361b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (!(*rootp)->child[0]) { 362b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (!(*rootp)->child[1]) { 363b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp) = 0; 364b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 365b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 366b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp) = (*rootp)->child[1]; 367b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 368b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 369b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (!(*rootp)->child[1]) { 370b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp) = (*rootp)->child[0]; 371b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 372b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 373b411202f9ff33a587558e2e836626bc7eb9db183sewardj if ((*rootp)->balance < 0) { 374b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* remove from the left subtree */ 375b411202f9ff33a587558e2e836626bc7eb9db183sewardj a = (*rootp)->child[0]; 376b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (a->child[1]) a = a->child[1]; 377b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 378b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* remove from the right subtree */ 379b411202f9ff33a587558e2e836626bc7eb9db183sewardj a = (*rootp)->child[1]; 380b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (a->child[0]) a = a->child[0]; 381b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 382b411202f9ff33a587558e2e836626bc7eb9db183sewardj ch = avl_remove_wrk(rootp, a, kCmp); 383b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[0] = (*rootp)->child[0]; 384b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->child[1] = (*rootp)->child[1]; 385b411202f9ff33a587558e2e836626bc7eb9db183sewardj a->balance = (*rootp)->balance; 386b411202f9ff33a587558e2e836626bc7eb9db183sewardj (*rootp) = a; 387b411202f9ff33a587558e2e836626bc7eb9db183sewardj if(a->balance == 0) return ch; 388b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 389b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 390b411202f9ff33a587558e2e836626bc7eb9db183sewardj 391b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic 392250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardjAvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(UWord,UWord) ) 393b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 394b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (kCmp) { 395b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Boxed comparisons */ 39695e790018ed15cf1f6d656b7c7973e18a77f975asewardj Word cmpresS; 397b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (True) { 398b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (t == NULL) return NULL; 39995e790018ed15cf1f6d656b7c7973e18a77f975asewardj cmpresS = kCmp(t->key, k); 40095e790018ed15cf1f6d656b7c7973e18a77f975asewardj if (cmpresS > 0) t = t->child[0]; else 40195e790018ed15cf1f6d656b7c7973e18a77f975asewardj if (cmpresS < 0) t = t->child[1]; else 402b411202f9ff33a587558e2e836626bc7eb9db183sewardj return t; 403b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 404b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 405b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Unboxed comparisons */ 40695e790018ed15cf1f6d656b7c7973e18a77f975asewardj Word cmpresS; /* signed */ 407b411202f9ff33a587558e2e836626bc7eb9db183sewardj UWord cmpresU; /* unsigned */ 408b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (True) { 409b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (t == NULL) return NULL; /* unlikely ==> predictable */ 410250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj cmpresS = cmp_unsigned_Words( (UWord)t->key, (UWord)k ); 41195e790018ed15cf1f6d656b7c7973e18a77f975asewardj if (cmpresS == 0) return t; /* unlikely ==> predictable */ 41295e790018ed15cf1f6d656b7c7973e18a77f975asewardj cmpresU = (UWord)cmpresS; 413efd3b4d91417ba085710206dcfdbbf5bf8ccfc8dsewardj cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1); 414b411202f9ff33a587558e2e836626bc7eb9db183sewardj t = t->child[cmpresU]; 415b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 416b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 417b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 418b411202f9ff33a587558e2e836626bc7eb9db183sewardj 4199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic 420ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianBool avl_find_bounds ( const AvlNode* t, 4219520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP, 4229520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP, 4239520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord minKey, UWord minVal, 4249520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord maxKey, UWord maxVal, 4259520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord key, 4269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj Word(*kCmp)(UWord,UWord) ) 4279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{ 4289520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord kLowerBound = minKey; 4299520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord vLowerBound = minVal; 4309520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord kUpperBound = maxKey; 4319520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord vUpperBound = maxVal; 4329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj while (t) { 4339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj Word cmpresS = kCmp ? kCmp(t->key, key) 4349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj : cmp_unsigned_Words(t->key, key); 4359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj if (cmpresS < 0) { 4369520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj kLowerBound = t->key; 4379520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj vLowerBound = t->val; 4389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj t = t->child[1]; 4399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj continue; 4409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj } 4419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj if (cmpresS > 0) { 4429520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj kUpperBound = t->key; 4439520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj vUpperBound = t->val; 4449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj t = t->child[0]; 4459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj continue; 4469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj } 4479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj /* We should never get here. If we do, it means the given key 4489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj is actually present in the tree, which means the original 4499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj call was invalid -- an error on the caller's part, and we 4509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj cannot give any meaningful values for the bounds. (Well, 4519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj maybe we could, but we're not gonna. Ner!) */ 4529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj return False; 4539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj } 4549520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj if (kMinP) *kMinP = kLowerBound; 4559520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj if (vMinP) *vMinP = vLowerBound; 4569520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj if (kMaxP) *kMaxP = kUpperBound; 4579520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj if (vMaxP) *vMaxP = vUpperBound; 4589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj return True; 4599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj} 4609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj 461b411202f9ff33a587558e2e836626bc7eb9db183sewardj// Clear the iterator stack. 462b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void stackClear(WordFM* fm) 463b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 464b411202f9ff33a587558e2e836626bc7eb9db183sewardj Int i; 465e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm); 466b411202f9ff33a587558e2e836626bc7eb9db183sewardj for (i = 0; i < WFM_STKMAX; i++) { 467b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->nodeStack[i] = NULL; 468b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->numStack[i] = 0; 469b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 470b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->stackTop = 0; 471b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 472b411202f9ff33a587558e2e836626bc7eb9db183sewardj 473b411202f9ff33a587558e2e836626bc7eb9db183sewardj// Push onto the iterator stack. 474b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic inline void stackPush(WordFM* fm, AvlNode* n, Int i) 475b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 476e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm->stackTop < WFM_STKMAX); 477e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(1 <= i && i <= 3); 478b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->nodeStack[fm->stackTop] = n; 479b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm-> numStack[fm->stackTop] = i; 480b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->stackTop++; 481b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 482b411202f9ff33a587558e2e836626bc7eb9db183sewardj 483b411202f9ff33a587558e2e836626bc7eb9db183sewardj// Pop from the iterator stack. 484b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic inline Bool stackPop(WordFM* fm, AvlNode** n, Int* i) 485b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 486e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm->stackTop <= WFM_STKMAX); 487b411202f9ff33a587558e2e836626bc7eb9db183sewardj 488b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (fm->stackTop > 0) { 489b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->stackTop--; 490b411202f9ff33a587558e2e836626bc7eb9db183sewardj *n = fm->nodeStack[fm->stackTop]; 491b411202f9ff33a587558e2e836626bc7eb9db183sewardj *i = fm-> numStack[fm->stackTop]; 492e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(1 <= *i && *i <= 3); 493b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->nodeStack[fm->stackTop] = NULL; 494b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm-> numStack[fm->stackTop] = 0; 495b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 496b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 497b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 498b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 499b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 500b411202f9ff33a587558e2e836626bc7eb9db183sewardj 501b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic 502ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianAvlNode* avl_dopy ( const AvlNode* nd, 503250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord(*dopyK)(UWord), 504250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord(*dopyV)(UWord), 50554fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian void*(alloc_nofail)(const HChar*,SizeT), 50654fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian const HChar* cc ) 507b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 508b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* nyu; 5096aa8bd03abedae0a3d210eaaf76b2f25775b731aflorian 5106aa8bd03abedae0a3d210eaaf76b2f25775b731aflorian vg_assert(nd != NULL); 5116aa8bd03abedae0a3d210eaaf76b2f25775b731aflorian 5129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj nyu = alloc_nofail(cc, sizeof(AvlNode)); 513b411202f9ff33a587558e2e836626bc7eb9db183sewardj 514b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->child[0] = nd->child[0]; 515b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->child[1] = nd->child[1]; 516b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->balance = nd->balance; 517b411202f9ff33a587558e2e836626bc7eb9db183sewardj 518b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Copy key */ 519b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (dopyK) { 520b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->key = dopyK( nd->key ); 521b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 522b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* copying assumedly unboxed keys */ 523b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->key = nd->key; 524b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 525b411202f9ff33a587558e2e836626bc7eb9db183sewardj 526b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Copy val */ 527b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (dopyV) { 528b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->val = dopyV( nd->val ); 529b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 530b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* copying assumedly unboxed vals */ 531b411202f9ff33a587558e2e836626bc7eb9db183sewardj nyu->val = nd->val; 532b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 533b411202f9ff33a587558e2e836626bc7eb9db183sewardj 534b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Copy subtrees */ 535b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nyu->child[0]) { 5369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj nyu->child[0] = avl_dopy( nyu->child[0], dopyK, dopyV, 5379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj alloc_nofail, cc ); 538b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 539b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nyu->child[1]) { 5409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj nyu->child[1] = avl_dopy( nyu->child[1], dopyK, dopyV, 5419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj alloc_nofail, cc ); 542b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 543b411202f9ff33a587558e2e836626bc7eb9db183sewardj 544b411202f9ff33a587558e2e836626bc7eb9db183sewardj return nyu; 545b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 546b411202f9ff33a587558e2e836626bc7eb9db183sewardj 547b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Initialise a WordFM. */ 548b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void initFM ( WordFM* fm, 54954fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian void* (*alloc_nofail)( const HChar*, SizeT ), 55054fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian const HChar* cc, 551b411202f9ff33a587558e2e836626bc7eb9db183sewardj void (*dealloc)(void*), 552250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word (*kCmp)(UWord,UWord) ) 553b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 554b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->root = 0; 555b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->kCmp = kCmp; 556b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->alloc_nofail = alloc_nofail; 5579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj fm->cc = cc; 558b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->dealloc = dealloc; 559b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->stackTop = 0; 560b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 561b411202f9ff33a587558e2e836626bc7eb9db183sewardj 562b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* --- Public interface functions --- */ 563b411202f9ff33a587558e2e836626bc7eb9db183sewardj 564250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj/* Allocate and initialise a WordFM. If kCmp is non-NULL, elements in 565250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj the set are ordered according to the ordering specified by kCmp, 566250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj which becomes obvious if you use VG_(initIterFM), 567250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj VG_(initIterAtFM), VG_(nextIterFM), VG_(doneIterFM) to iterate over 568fc4b63a0b28c270356bd001453415a7f683ac370sewardj sections of the map, or the whole thing. If kCmp is NULL then the 569fc4b63a0b28c270356bd001453415a7f683ac370sewardj ordering used is unsigned word ordering (UWord) on the key 570fc4b63a0b28c270356bd001453415a7f683ac370sewardj values. */ 57154fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianWordFM* VG_(newFM) ( void* (*alloc_nofail)( const HChar*, SizeT ), 57254fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian const HChar* cc, 573b411202f9ff33a587558e2e836626bc7eb9db183sewardj void (*dealloc)(void*), 574250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj Word (*kCmp)(UWord,UWord) ) 575b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 5769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj WordFM* fm = alloc_nofail(cc, sizeof(WordFM)); 5779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj initFM(fm, alloc_nofail, cc, dealloc, kCmp); 578b411202f9ff33a587558e2e836626bc7eb9db183sewardj return fm; 579b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 580b411202f9ff33a587558e2e836626bc7eb9db183sewardj 581b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic void avl_free ( AvlNode* nd, 582250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj void(*kFin)(UWord), 583250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj void(*vFin)(UWord), 584b411202f9ff33a587558e2e836626bc7eb9db183sewardj void(*dealloc)(void*) ) 585b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 586b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (!nd) 587b411202f9ff33a587558e2e836626bc7eb9db183sewardj return; 588b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nd->child[0]) 589b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_free(nd->child[0], kFin, vFin, dealloc); 590b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nd->child[1]) 591b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_free(nd->child[1], kFin, vFin, dealloc); 592b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (kFin) 593b411202f9ff33a587558e2e836626bc7eb9db183sewardj kFin( nd->key ); 594b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (vFin) 595b411202f9ff33a587558e2e836626bc7eb9db183sewardj vFin( nd->val ); 596b411202f9ff33a587558e2e836626bc7eb9db183sewardj VG_(memset)(nd, 0, sizeof(AvlNode)); 597b411202f9ff33a587558e2e836626bc7eb9db183sewardj dealloc(nd); 598b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 599b411202f9ff33a587558e2e836626bc7eb9db183sewardj 600b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Free up the FM. If kFin is non-NULL, it is applied to keys 601b411202f9ff33a587558e2e836626bc7eb9db183sewardj before the FM is deleted; ditto with vFin for vals. */ 602896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(deleteFM) ( WordFM* fm, void(*kFin)(UWord), void(*vFin)(UWord) ) 603b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 604b411202f9ff33a587558e2e836626bc7eb9db183sewardj void(*dealloc)(void*) = fm->dealloc; 605b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_free( fm->root, kFin, vFin, dealloc ); 606b411202f9ff33a587558e2e836626bc7eb9db183sewardj VG_(memset)(fm, 0, sizeof(WordFM) ); 607b411202f9ff33a587558e2e836626bc7eb9db183sewardj dealloc(fm); 608b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 609b411202f9ff33a587558e2e836626bc7eb9db183sewardj 610b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Add (k,v) to fm. */ 6119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjBool VG_(addToFM) ( WordFM* fm, UWord k, UWord v ) 612b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 613b411202f9ff33a587558e2e836626bc7eb9db183sewardj MaybeWord oldV; 614b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* node; 615d86e3a28694ca5a7c59881475b8d1f6c9ac285b0sewardj node = fm->alloc_nofail( fm->cc, sizeof(AvlNode) ); 616b411202f9ff33a587558e2e836626bc7eb9db183sewardj node->key = k; 617b411202f9ff33a587558e2e836626bc7eb9db183sewardj node->val = v; 618b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldV.b = False; 619b411202f9ff33a587558e2e836626bc7eb9db183sewardj oldV.w = 0; 620b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_insert_wrk( &fm->root, &oldV, node, fm->kCmp ); 621b411202f9ff33a587558e2e836626bc7eb9db183sewardj //if (oldV.b && fm->vFin) 622b411202f9ff33a587558e2e836626bc7eb9db183sewardj // fm->vFin( oldV.w ); 623b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (oldV.b) 624b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->dealloc(node); 6259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj return oldV.b; 626b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 627b411202f9ff33a587558e2e836626bc7eb9db183sewardj 628b411202f9ff33a587558e2e836626bc7eb9db183sewardj// Delete key from fm, returning associated key and val if found 629896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjBool VG_(delFromFM) ( WordFM* fm, 630250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj /*OUT*/UWord* oldK, /*OUT*/UWord* oldV, UWord key ) 631b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 632b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* node = avl_find_node( fm->root, key, fm->kCmp ); 633b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (node) { 634b411202f9ff33a587558e2e836626bc7eb9db183sewardj avl_remove_wrk( &fm->root, node, fm->kCmp ); 635b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (oldK) 636b411202f9ff33a587558e2e836626bc7eb9db183sewardj *oldK = node->key; 637b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (oldV) 638b411202f9ff33a587558e2e836626bc7eb9db183sewardj *oldV = node->val; 639b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->dealloc(node); 640b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 641b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 642b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 643b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 644b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 645b411202f9ff33a587558e2e836626bc7eb9db183sewardj 646b411202f9ff33a587558e2e836626bc7eb9db183sewardj// Look up in fm, assigning found key & val at spec'd addresses 647ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianBool VG_(lookupFM) ( const WordFM* fm, 648250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj /*OUT*/UWord* keyP, /*OUT*/UWord* valP, UWord key ) 649b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 650b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* node = avl_find_node( fm->root, key, fm->kCmp ); 651b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (node) { 652b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (keyP) 653b411202f9ff33a587558e2e836626bc7eb9db183sewardj *keyP = node->key; 654b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (valP) 655b411202f9ff33a587558e2e836626bc7eb9db183sewardj *valP = node->val; 656b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 657b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 658b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 659b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 660b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 661b411202f9ff33a587558e2e836626bc7eb9db183sewardj 6629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// See comment in pub_tool_wordfm.h for explanation 663ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianBool VG_(findBoundsFM)( const WordFM* fm, 6649520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP, 6659520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP, 6669520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord minKey, UWord minVal, 6679520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord maxKey, UWord maxVal, 6689520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj UWord key ) 6699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{ 670f8aecf47bb53b90e00c4a04210056ecf00a0f770sewardj /* really we should assert that minKey <= key <= maxKey, 671f8aecf47bb53b90e00c4a04210056ecf00a0f770sewardj where <= is as defined by fm->kCmp. */ 6729520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj return avl_find_bounds( fm->root, kMinP, vMinP, 6739520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj kMaxP, vMaxP, 6749520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj minKey, minVal, 6759520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj maxKey, maxVal, 6769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj key, fm->kCmp ); 6779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj} 6789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj 6790b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj// See comment in pub_tool_wordfm.h for performance warning 680ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianUWord VG_(sizeFM) ( const WordFM* fm ) 681b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 682b411202f9ff33a587558e2e836626bc7eb9db183sewardj // Hmm, this is a bad way to do this 683b411202f9ff33a587558e2e836626bc7eb9db183sewardj return fm->root ? size_avl_nonNull( fm->root ) : 0; 684b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 685b411202f9ff33a587558e2e836626bc7eb9db183sewardj 6860b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj// NB UNTESTED! TEST BEFORE USE! 687ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorian//Bool VG_(isEmptyFM)( const WordFM* fm ) 6880b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj//{ 6890b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj// return fm->root ? False : True; 6900b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj//} 6910b5f9fcf5069d7c9e8d1f91c04b528262c65805dsewardj 692b411202f9ff33a587558e2e836626bc7eb9db183sewardj// set up FM for iteration 693896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(initIterFM) ( WordFM* fm ) 694b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 695e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm); 696b411202f9ff33a587558e2e836626bc7eb9db183sewardj stackClear(fm); 697b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (fm->root) 698b411202f9ff33a587558e2e836626bc7eb9db183sewardj stackPush(fm, fm->root, 1); 699b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 700b411202f9ff33a587558e2e836626bc7eb9db183sewardj 701250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj// set up FM for iteration so that the first key subsequently produced 702896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj// by VG_(nextIterFM) is the smallest key in the map >= start_at. 703250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj// Naturally ">=" is defined by the comparison function supplied to 704896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj// VG_(newFM), as documented above. 705896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(initIterAtFM) ( WordFM* fm, UWord start_at ) 706ae5137e9532a4625e54fcbf103e146815717852bsewardj{ 707ae5137e9532a4625e54fcbf103e146815717852bsewardj Int i; 708ae5137e9532a4625e54fcbf103e146815717852bsewardj AvlNode *n, *t; 709ae5137e9532a4625e54fcbf103e146815717852bsewardj Word cmpresS; /* signed */ 710ae5137e9532a4625e54fcbf103e146815717852bsewardj UWord cmpresU; /* unsigned */ 711ae5137e9532a4625e54fcbf103e146815717852bsewardj 712e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm); 713ae5137e9532a4625e54fcbf103e146815717852bsewardj stackClear(fm); 714ae5137e9532a4625e54fcbf103e146815717852bsewardj 715ae5137e9532a4625e54fcbf103e146815717852bsewardj if (!fm->root) 716ae5137e9532a4625e54fcbf103e146815717852bsewardj return; 717ae5137e9532a4625e54fcbf103e146815717852bsewardj 718ae5137e9532a4625e54fcbf103e146815717852bsewardj n = NULL; 719ae5137e9532a4625e54fcbf103e146815717852bsewardj // We need to do regular search and fill in the stack. 720ae5137e9532a4625e54fcbf103e146815717852bsewardj t = fm->root; 721ae5137e9532a4625e54fcbf103e146815717852bsewardj 722ae5137e9532a4625e54fcbf103e146815717852bsewardj while (True) { 723ae5137e9532a4625e54fcbf103e146815717852bsewardj if (t == NULL) return; 724ae5137e9532a4625e54fcbf103e146815717852bsewardj 725ae5137e9532a4625e54fcbf103e146815717852bsewardj cmpresS 726ae5137e9532a4625e54fcbf103e146815717852bsewardj = fm->kCmp ? /*boxed*/ fm->kCmp( t->key, start_at ) 727250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj : /*unboxed*/ cmp_unsigned_Words( t->key, start_at ); 728ae5137e9532a4625e54fcbf103e146815717852bsewardj 729ae5137e9532a4625e54fcbf103e146815717852bsewardj if (cmpresS == 0) { 730ae5137e9532a4625e54fcbf103e146815717852bsewardj // We found the exact key -- we are done. 731ae5137e9532a4625e54fcbf103e146815717852bsewardj // The iteration should start with this node. 732ae5137e9532a4625e54fcbf103e146815717852bsewardj stackPush(fm, t, 2); 733ae5137e9532a4625e54fcbf103e146815717852bsewardj // The stack now looks like {2, 2, ... ,2, 2} 734ae5137e9532a4625e54fcbf103e146815717852bsewardj return; 735ae5137e9532a4625e54fcbf103e146815717852bsewardj } 736ae5137e9532a4625e54fcbf103e146815717852bsewardj cmpresU = (UWord)cmpresS; 737ae5137e9532a4625e54fcbf103e146815717852bsewardj cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1); 738ae5137e9532a4625e54fcbf103e146815717852bsewardj if (!cmpresU) { 739ae5137e9532a4625e54fcbf103e146815717852bsewardj // Push this node only if we go to the left child. 740ae5137e9532a4625e54fcbf103e146815717852bsewardj stackPush(fm, t, 2); 741ae5137e9532a4625e54fcbf103e146815717852bsewardj } 742ae5137e9532a4625e54fcbf103e146815717852bsewardj t = t->child[cmpresU]; 743ae5137e9532a4625e54fcbf103e146815717852bsewardj } 744ae5137e9532a4625e54fcbf103e146815717852bsewardj if (stackPop(fm, &n, &i)) { 745ae5137e9532a4625e54fcbf103e146815717852bsewardj // If we've pushed something to stack and did not find the exact key, 746ae5137e9532a4625e54fcbf103e146815717852bsewardj // we must fix the top element of stack. 747e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(i == 2); 748ae5137e9532a4625e54fcbf103e146815717852bsewardj stackPush(fm, n, 3); 749ae5137e9532a4625e54fcbf103e146815717852bsewardj // the stack looks like {2, 2, ..., 2, 3} 750ae5137e9532a4625e54fcbf103e146815717852bsewardj } 751ae5137e9532a4625e54fcbf103e146815717852bsewardj} 752ae5137e9532a4625e54fcbf103e146815717852bsewardj 753e2800c958044937e72eefa371c10ae47ac40e089florian// get next key/val pair. Will vg_assert if fm has been modified 754ae5137e9532a4625e54fcbf103e146815717852bsewardj// or looked up in since initIter{,At}FM was called. 755896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjBool VG_(nextIterFM) ( WordFM* fm, /*OUT*/UWord* pKey, /*OUT*/UWord* pVal ) 756b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 757b411202f9ff33a587558e2e836626bc7eb9db183sewardj Int i = 0; 758b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* n = NULL; 759b411202f9ff33a587558e2e836626bc7eb9db183sewardj 760e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm); 761b411202f9ff33a587558e2e836626bc7eb9db183sewardj 762b411202f9ff33a587558e2e836626bc7eb9db183sewardj // This in-order traversal requires each node to be pushed and popped 763b411202f9ff33a587558e2e836626bc7eb9db183sewardj // three times. These could be avoided by updating nodes in-situ on the 764b411202f9ff33a587558e2e836626bc7eb9db183sewardj // top of the stack, but the push/pop cost is so small that it's worth 765b411202f9ff33a587558e2e836626bc7eb9db183sewardj // keeping this loop in this simpler form. 766b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (stackPop(fm, &n, &i)) { 767b411202f9ff33a587558e2e836626bc7eb9db183sewardj switch (i) { 768b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 1: case_1: 769b411202f9ff33a587558e2e836626bc7eb9db183sewardj stackPush(fm, n, 2); 770b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* if (n->child[0]) stackPush(fm, n->child[0], 1); */ 771b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (n->child[0]) { n = n->child[0]; goto case_1; } 772b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 773b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 2: 774b411202f9ff33a587558e2e836626bc7eb9db183sewardj stackPush(fm, n, 3); 775b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (pKey) *pKey = n->key; 776b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (pVal) *pVal = n->val; 777b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 778b411202f9ff33a587558e2e836626bc7eb9db183sewardj case 3: 779b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* if (n->child[1]) stackPush(fm, n->child[1], 1); */ 780b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (n->child[1]) { n = n->child[1]; goto case_1; } 781b411202f9ff33a587558e2e836626bc7eb9db183sewardj break; 782b411202f9ff33a587558e2e836626bc7eb9db183sewardj default: 783e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(0); 784b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 785b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 786b411202f9ff33a587558e2e836626bc7eb9db183sewardj 787b411202f9ff33a587558e2e836626bc7eb9db183sewardj // Stack empty, iterator is exhausted, return NULL 788b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 789b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 790b411202f9ff33a587558e2e836626bc7eb9db183sewardj 7916aa8bd03abedae0a3d210eaaf76b2f25775b731aflorian// Finish an FM iteration 792896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(doneIterFM) ( WordFM* fm ) 793b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 794b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 795b411202f9ff33a587558e2e836626bc7eb9db183sewardj 796ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianWordFM* VG_(dopyFM) ( WordFM* fm, UWord(*dopyK)(UWord), 797ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorian UWord(*dopyV)(UWord) ) 798b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 799b411202f9ff33a587558e2e836626bc7eb9db183sewardj WordFM* nyu; 800b411202f9ff33a587558e2e836626bc7eb9db183sewardj 801b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* can't clone the fm whilst iterating on it */ 802e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(fm->stackTop == 0); 803b411202f9ff33a587558e2e836626bc7eb9db183sewardj 8049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj nyu = fm->alloc_nofail( fm->cc, sizeof(WordFM) ); 805b411202f9ff33a587558e2e836626bc7eb9db183sewardj 806b411202f9ff33a587558e2e836626bc7eb9db183sewardj *nyu = *fm; 807b411202f9ff33a587558e2e836626bc7eb9db183sewardj 808b411202f9ff33a587558e2e836626bc7eb9db183sewardj fm->stackTop = 0; 809b411202f9ff33a587558e2e836626bc7eb9db183sewardj VG_(memset)(fm->nodeStack, 0, sizeof(fm->nodeStack)); 810b411202f9ff33a587558e2e836626bc7eb9db183sewardj VG_(memset)(fm->numStack, 0, sizeof(fm->numStack)); 811b411202f9ff33a587558e2e836626bc7eb9db183sewardj 812b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nyu->root) { 8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj nyu->root = avl_dopy( nyu->root, dopyK, dopyV, 8149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj fm->alloc_nofail, fm->cc ); 815b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (! nyu->root) 816b411202f9ff33a587558e2e836626bc7eb9db183sewardj return NULL; 817b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 818b411202f9ff33a587558e2e836626bc7eb9db183sewardj 819b411202f9ff33a587558e2e836626bc7eb9db183sewardj return nyu; 820b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 821b411202f9ff33a587558e2e836626bc7eb9db183sewardj 822b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 823b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- end WordFM ---// 824b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- Implementation ---// 825b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 826b411202f9ff33a587558e2e836626bc7eb9db183sewardj 827b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 828b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- WordBag (unboxed words only) ---// 829b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- Implementation ---// 830b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 831b411202f9ff33a587558e2e836626bc7eb9db183sewardj 832b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* A trivial container, to make it opaque. */ 833b411202f9ff33a587558e2e836626bc7eb9db183sewardjstruct _WordBag { 834b411202f9ff33a587558e2e836626bc7eb9db183sewardj WordFM* fm; 835b411202f9ff33a587558e2e836626bc7eb9db183sewardj}; 836b411202f9ff33a587558e2e836626bc7eb9db183sewardj 83754fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianWordBag* VG_(newBag) ( void* (*alloc_nofail)( const HChar*, SizeT ), 83854fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian const HChar* cc, 839b411202f9ff33a587558e2e836626bc7eb9db183sewardj void (*dealloc)(void*) ) 840b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 8419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj WordBag* bag = alloc_nofail(cc, sizeof(WordBag)); 8429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj bag->fm = VG_(newFM)( alloc_nofail, cc, dealloc, NULL ); 843b411202f9ff33a587558e2e836626bc7eb9db183sewardj return bag; 844b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 845b411202f9ff33a587558e2e836626bc7eb9db183sewardj 846896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(deleteBag) ( WordBag* bag ) 847b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 848b411202f9ff33a587558e2e836626bc7eb9db183sewardj void (*dealloc)(void*) = bag->fm->dealloc; 849896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(deleteFM)( bag->fm, NULL, NULL ); 850b411202f9ff33a587558e2e836626bc7eb9db183sewardj VG_(memset)(bag, 0, sizeof(WordBag)); 851b411202f9ff33a587558e2e836626bc7eb9db183sewardj dealloc(bag); 852b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 853b411202f9ff33a587558e2e836626bc7eb9db183sewardj 854896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(addToBag)( WordBag* bag, UWord w ) 855b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 856250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord key, count; 857896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj if (VG_(lookupFM)(bag->fm, &key, &count, w)) { 858e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(key == w); 859e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(count >= 1); 860896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(addToFM)(bag->fm, w, count+1); 861b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 862896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(addToFM)(bag->fm, w, 1); 863b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 864b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 865b411202f9ff33a587558e2e836626bc7eb9db183sewardj 866ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianUWord VG_(elemBag) ( const WordBag* bag, UWord w ) 867b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 868250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord key, count; 869896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj if (VG_(lookupFM)( bag->fm, &key, &count, w)) { 870e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(key == w); 871e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(count >= 1); 872b411202f9ff33a587558e2e836626bc7eb9db183sewardj return count; 873b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 874b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 0; 875b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 876b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 877b411202f9ff33a587558e2e836626bc7eb9db183sewardj 878ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianUWord VG_(sizeUniqueBag) ( const WordBag* bag ) 879b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 880896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj return VG_(sizeFM)( bag->fm ); 881b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 882b411202f9ff33a587558e2e836626bc7eb9db183sewardj 883ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianstatic UWord sizeTotalBag_wrk ( const AvlNode* nd ) 884b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 885b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* unchecked pre: nd is non-NULL */ 886250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord w = nd->val; 887e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(w >= 1); 888b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nd->child[0]) 889b411202f9ff33a587558e2e836626bc7eb9db183sewardj w += sizeTotalBag_wrk(nd->child[0]); 890b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (nd->child[1]) 891b411202f9ff33a587558e2e836626bc7eb9db183sewardj w += sizeTotalBag_wrk(nd->child[1]); 892b411202f9ff33a587558e2e836626bc7eb9db183sewardj return w; 893b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 894ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianUWord VG_(sizeTotalBag)( const WordBag* bag ) 895b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 896b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (bag->fm->root) 897b411202f9ff33a587558e2e836626bc7eb9db183sewardj return sizeTotalBag_wrk(bag->fm->root); 898b411202f9ff33a587558e2e836626bc7eb9db183sewardj else 899b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 0; 900b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 901b411202f9ff33a587558e2e836626bc7eb9db183sewardj 902896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjBool VG_(delFromBag)( WordBag* bag, UWord w ) 903b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 904250ec2eb29b4afec646bdc8ecbfcdbb7d73d0b23sewardj UWord key, count; 905896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj if (VG_(lookupFM)(bag->fm, &key, &count, w)) { 906e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(key == w); 907e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(count >= 1); 908b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (count > 1) { 909896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(addToFM)(bag->fm, w, count-1); 910b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 911e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(count == 1); 912896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(delFromFM)( bag->fm, NULL, NULL, w ); 913b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 914b411202f9ff33a587558e2e836626bc7eb9db183sewardj return True; 915b411202f9ff33a587558e2e836626bc7eb9db183sewardj } else { 916b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 917b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 918b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 919b411202f9ff33a587558e2e836626bc7eb9db183sewardj 920ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianBool VG_(isEmptyBag)( const WordBag* bag ) 921b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 922896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj return VG_(sizeFM)(bag->fm) == 0; 923b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 924b411202f9ff33a587558e2e836626bc7eb9db183sewardj 925ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianBool VG_(isSingletonTotalBag)( const WordBag* bag ) 926b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 927b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* nd; 928896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj if (VG_(sizeFM)(bag->fm) != 1) 929b411202f9ff33a587558e2e836626bc7eb9db183sewardj return False; 930b411202f9ff33a587558e2e836626bc7eb9db183sewardj nd = bag->fm->root; 931e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(nd); 932e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(!nd->child[0]); 933e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(!nd->child[1]); 934b411202f9ff33a587558e2e836626bc7eb9db183sewardj return nd->val == 1; 935b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 936b411202f9ff33a587558e2e836626bc7eb9db183sewardj 937ee0d0e9cd0351721260f8b079495ed9d5ecf5fafflorianUWord VG_(anyElementOfBag)( const WordBag* bag ) 938b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 939b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Return an arbitrarily chosen element in the bag. We might as 940b411202f9ff33a587558e2e836626bc7eb9db183sewardj well return the one at the root of the underlying AVL tree. */ 941b411202f9ff33a587558e2e836626bc7eb9db183sewardj AvlNode* nd = bag->fm->root; 942e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(nd); /* if this fails, 'bag' is empty - caller is in error. */ 943e2800c958044937e72eefa371c10ae47ac40e089florian vg_assert(nd->val >= 1); 944b411202f9ff33a587558e2e836626bc7eb9db183sewardj return nd->key; 945b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 946b411202f9ff33a587558e2e836626bc7eb9db183sewardj 947896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(initIterBag)( WordBag* bag ) 948b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 949896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(initIterFM)(bag->fm); 950b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 951b411202f9ff33a587558e2e836626bc7eb9db183sewardj 952896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjBool VG_(nextIterBag)( WordBag* bag, /*OUT*/UWord* pVal, /*OUT*/UWord* pCount ) 953b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 954896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj return VG_(nextIterFM)( bag->fm, pVal, pCount ); 955b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 956b411202f9ff33a587558e2e836626bc7eb9db183sewardj 957896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardjvoid VG_(doneIterBag)( WordBag* bag ) 958b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 959896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj VG_(doneIterFM)( bag->fm ); 960b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 961b411202f9ff33a587558e2e836626bc7eb9db183sewardj 962b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 963b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- end WordBag (unboxed words only) ---// 964b411202f9ff33a587558e2e836626bc7eb9db183sewardj//--- Implementation ---// 965b411202f9ff33a587558e2e836626bc7eb9db183sewardj//------------------------------------------------------------------// 966b411202f9ff33a587558e2e836626bc7eb9db183sewardj 967b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--------------------------------------------------------------------*/ 968896f6f996a8bb1f5ac1e7e0272b039bf4c16c40asewardj/*--- end m_wordfm.c ---*/ 969b411202f9ff33a587558e2e836626bc7eb9db183sewardj/*--------------------------------------------------------------------*/ 970