add missing includes, makefile updates
[libfirm] / ir / adt / arrayset.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file   arrayset.c
22  * @brief  Implementation of sets with sorted arrays.
23  * @date   11.07.2007
24  * @author Sebastian Hack
25  *
26  * Follows the same API/specialization scheme as hashset.c and is thus interchangable.
27  * To remain compatible, all specializations as in hashset.c must be done.
28  * Additionally, we need a ValueCmp macro comapring two values not only for equality.
29  * That macro follows the same scheme as the compare functions in qsort(3).
30  */
31
32 #ifdef HashSet
33
34 #include "firm_config.h"
35 #include "array.h"
36
37 static INLINE int hashset_bsearch(ValueType *arr, const ValueType elm)
38 {
39         int res = 0;
40         int lo  = 0;
41         int hi  = ARR_LEN(arr);
42
43         while(lo < hi) {
44                 int md     = lo + ((hi - lo) >> 1);
45                 int cmp    = ValueCmp(arr[md], elm);
46
47                 if(cmp < 0)
48                         lo = md + 1;
49                 else if(cmp > 0)
50                         hi = md;
51                 else {
52                         res = md;
53                         break;
54                 }
55
56                 res = lo;
57         }
58
59         return res;
60 }
61
62 static INLINE int hashset_is_at(ValueType *arr, int idx, const ValueType what)
63 {
64         return idx < ARR_LEN(arr) && ValueCmp(arr[idx], what) == 0;
65 }
66
67 void hashset_init_size(HashSet *set, size_t expected_elements)
68 {
69         set->arr = NEW_ARR_F(ValueType, expected_elements);
70 #ifndef NDEBUG
71         set->in_order = 1;
72 #endif
73         ARR_SHRINKLEN(set->arr, 0);
74 }
75
76 void hashset_init(HashSet *set)
77 {
78         hashset_init_size(set, 16);
79 }
80
81 void hashset_destroy(HashSet *set)
82 {
83         DEL_ARR_F(set->arr);
84 }
85
86 int hashset_insert(HashSet *set, ValueType elt)
87 {
88         ValueType *arr = set->arr;
89         int i, idx     = hashset_bsearch(arr, elt);
90
91 #ifndef NDEBUG
92         assert(set->in_order);
93 #endif
94         if (!hashset_is_at(arr, idx, elt)) {
95                 ARR_EXTEND(ValueType, set->arr, 1);
96                 arr = set->arr;
97                 for (i = ARR_LEN(arr) - 1; i > idx; --i)
98                         arr[i] = arr[i - 1];
99                 arr[idx] = elt;
100                 return 1;
101         }
102
103         return 0;
104 }
105
106 void hashset_insert_quick(HashSet *set, ValueType elt)
107 {
108         ValueType *arr = set->arr;
109         ARR_EXTEND(ValueType, set->arr, 1);
110         arr = set->arr;
111         arr[ARR_LEN(arr) - 1] = elt;
112 }
113
114 static INLINE int _hashset_remove_idx(ValueType *arr, int idx)
115 {
116         int n;
117
118         for (n = ARR_LEN(arr) - 1; idx < n; ++idx)
119                 arr[idx] = arr[idx + 1];
120
121         return n;
122 }
123
124 void hashset_remove(HashSet *set, const ValueType elt)
125 {
126         ValueType *arr = set->arr;
127         int idx        = hashset_bsearch(arr, elt);
128
129 #ifndef NDEBUG
130         assert(set->in_order);
131 #endif
132         if (hashset_is_at(arr, idx, elt)) {
133                 int new_len = _hashset_remove_idx(arr, idx);
134                 ARR_SHRINKLEN(arr, new_len);
135         }
136 }
137
138 void hashset_remove_quick(HashSet *set, const ValueType elt)
139 {
140         ValueType *arr = set->arr;
141         int idx        = hashset_bsearch(arr, elt);
142
143 #ifndef NDEBUG
144         set->in_order = 0;
145 #endif
146         if (hashset_is_at(arr, idx, elt)) {
147                 int n = ARR_LEN(arr);
148                 if (idx < n - 1)
149                         arr[idx] = arr[n - 1];
150                 ARR_SHRINKLEN(arr, n - 1);
151         }
152 }
153
154 void hashset_fixup(HashSet *set)
155 {
156         ValueType *arr = set->arr;
157         ValueType *tmp;
158         int i, n;
159
160         CLONE_ARR_A(ValueType, tmp, arr);
161
162         memcpy(tmp, arr, n * sizeof(arr[0]));
163         ARR_SHRINKLEN(arr, 0);
164         for (i = 0, n = ARR_LEN(arr); i < n; ++i)
165                 hashset_insert(set, tmp[0]);
166 #ifndef NDEBUG
167         set->in_order = 1;
168 #endif
169 }
170
171 ValueType hashset_find(const HashSet *set, const ValueType elt)
172 {
173         int idx = hashset_bsearch(set->arr, elt);
174 #ifndef NDEBUG
175         assert(set->in_order);
176 #endif
177         return hashset_is_at(set->arr, idx, elt) ? set->arr[idx] : NullValue;
178 }
179
180 size_t hashset_size(const HashSet *set)
181 {
182         return ARR_LEN(set->arr);
183 }
184
185 void hashset_iterator_init(HashSetIterator *iter, const HashSet *set)
186 {
187         iter->arr  = set->arr;
188         iter->curr = -1;
189 }
190
191 ValueType ir_nodeset_iterator_next(HashSetIterator *iter)
192 {
193         ++iter->curr;
194         return iter->curr < ARR_LEN(iter->arr) ? iter->arr[iter->curr]  : NullValue;
195 }
196
197 void hashset_remove_iterator(HashSet *set, const HashSetIterator *iter)
198 {
199         (void) set;
200         (void) _hashset_remove_idx(iter->arr, iter->curr);
201         ARR_SHRINKLEN(iter->arr, ARR_LEN(iter->arr) - 1);
202 }
203
204 #endif