isl_output.c: remove some code duplication
[isl.git] / isl_hash.c
blob365082c3a8c404ef019abbf00b17d84f78437ef5
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
10 #include <stdlib.h>
11 #include <isl/hash.h>
12 #include <isl/ctx.h>
14 uint32_t isl_hash_string(uint32_t hash, const char *s)
16 for (; *s; s++)
17 isl_hash_byte(hash, *s);
18 return hash;
21 uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len)
23 int i;
24 const char *s = p;
25 for (i = 0; i < len; ++i)
26 isl_hash_byte(hash, s[i]);
27 return hash;
30 static unsigned int round_up(unsigned int v)
32 int old_v = v;
34 while (v) {
35 old_v = v;
36 v ^= v & -v;
38 return old_v << 1;
41 int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
42 int min_size)
44 size_t size;
46 if (!table)
47 return -1;
49 if (min_size < 2)
50 min_size = 2;
51 table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1;
52 table->n = 0;
54 size = 1 << table->bits;
55 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
56 size);
57 if (!table->entries)
58 return -1;
60 return 0;
63 static int grow_table(struct isl_ctx *ctx, struct isl_hash_table *table,
64 int (*eq)(const void *entry, const void *val))
66 size_t old_size, size;
67 struct isl_hash_table_entry *entries;
68 uint32_t h;
70 entries = table->entries;
71 old_size = 1 << table->bits;
72 size = 2 * old_size;
73 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
74 size);
75 if (!table->entries) {
76 table->entries = entries;
77 return -1;
80 table->bits++;
82 for (h = 0; h < old_size; ++h) {
83 struct isl_hash_table_entry *entry;
85 if (!entries[h].data)
86 continue;
88 entry = isl_hash_table_find(ctx, table, entries[h].hash,
89 eq, entries[h].data, 1);
90 if (!entry) {
91 table->bits--;
92 free(table->entries);
93 table->entries = entries;
94 return -1;
97 *entry = entries[h];
100 free(entries);
102 return 0;
105 struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size)
107 struct isl_hash_table *table = NULL;
109 table = isl_alloc_type(ctx, struct isl_hash_table);
110 if (isl_hash_table_init(ctx, table, min_size))
111 goto error;
112 return table;
113 error:
114 isl_hash_table_free(ctx, table);
115 return NULL;
118 void isl_hash_table_clear(struct isl_hash_table *table)
120 if (!table)
121 return;
122 free(table->entries);
125 void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
127 if (!table)
128 return;
129 isl_hash_table_clear(table);
130 free(table);
133 struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
134 struct isl_hash_table *table,
135 uint32_t key_hash,
136 int (*eq)(const void *entry, const void *val),
137 const void *val, int reserve)
139 size_t size;
140 uint32_t h, key_bits;
142 key_bits = isl_hash_bits(key_hash, table->bits);
143 size = 1 << table->bits;
144 for (h = key_bits; table->entries[h].data; h = (h+1) % size)
145 if (table->entries[h].hash == key_hash &&
146 eq(table->entries[h].data, val))
147 return &table->entries[h];
149 if (!reserve)
150 return NULL;
152 if (4 * table->n >= 3 * size) {
153 if (grow_table(ctx, table, eq) < 0)
154 return NULL;
155 return isl_hash_table_find(ctx, table, key_hash, eq, val, 1);
158 table->n++;
159 table->entries[h].hash = key_hash;
161 return &table->entries[h];
164 int isl_hash_table_foreach(struct isl_ctx *ctx,
165 struct isl_hash_table *table,
166 int (*fn)(void **entry, void *user), void *user)
168 size_t size;
169 uint32_t h;
171 size = 1 << table->bits;
172 for (h = 0; h < size; ++ h)
173 if (table->entries[h].data &&
174 fn(&table->entries[h].data, user) < 0)
175 return -1;
177 return 0;
180 void isl_hash_table_remove(struct isl_ctx *ctx,
181 struct isl_hash_table *table,
182 struct isl_hash_table_entry *entry)
184 int h, h2;
185 size_t size;
187 if (!table || !entry)
188 return;
190 size = 1 << table->bits;
191 h = entry - table->entries;
192 isl_assert(ctx, h >= 0 && h < size, return);
194 for (h2 = h+1; table->entries[h2 % size].data; h2++) {
195 uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash,
196 table->bits);
197 uint32_t offset = (size + bits - (h+1)) % size;
198 if (offset <= h2 - (h+1))
199 continue;
200 *entry = table->entries[h2 % size];
201 h = h2;
202 entry = &table->entries[h % size];
205 entry->hash = 0;
206 entry->data = NULL;
207 table->n--;