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