add isl_printer
[isl.git] / isl_hash.c
blob15df05af0e29cb83731ac709cb50c52a26646674
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 static unsigned int round_up(unsigned int v)
23 int old_v = v;
25 while (v) {
26 old_v = v;
27 v ^= v & -v;
29 return old_v << 1;
32 int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
33 int min_size)
35 size_t size;
37 if (!table)
38 return -1;
40 if (min_size < 2)
41 min_size = 2;
42 table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1;
43 table->n = 0;
45 size = 1 << table->bits;
46 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
47 size);
48 if (!table->entries)
49 return -1;
51 return 0;
54 static int grow_table(struct isl_ctx *ctx, struct isl_hash_table *table,
55 int (*eq)(const void *entry, const void *val))
57 size_t old_size, size;
58 struct isl_hash_table_entry *entries;
59 uint32_t h;
61 entries = table->entries;
62 old_size = 1 << table->bits;
63 size = 2 * old_size;
64 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
65 size);
66 if (!table->entries) {
67 table->entries = entries;
68 return -1;
71 table->bits++;
73 for (h = 0; h < old_size; ++h) {
74 struct isl_hash_table_entry *entry;
76 if (!entries[h].data)
77 continue;
79 entry = isl_hash_table_find(ctx, table, entries[h].hash,
80 eq, entries[h].data, 1);
81 if (!entry) {
82 table->bits--;
83 free(table->entries);
84 table->entries = entries;
85 return -1;
88 *entry = entries[h];
91 free(entries);
93 return 0;
96 struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size)
98 struct isl_hash_table *table = NULL;
100 table = isl_alloc_type(ctx, struct isl_hash_table);
101 if (isl_hash_table_init(ctx, table, min_size))
102 goto error;
103 return table;
104 error:
105 isl_hash_table_free(ctx, table);
106 return NULL;
109 void isl_hash_table_clear(struct isl_hash_table *table)
111 if (!table)
112 return;
113 free(table->entries);
116 void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
118 if (!table)
119 return;
120 isl_hash_table_clear(table);
121 free(table);
124 struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
125 struct isl_hash_table *table,
126 uint32_t key_hash,
127 int (*eq)(const void *entry, const void *val),
128 const void *val, int reserve)
130 size_t size;
131 uint32_t h, key_bits;
133 key_bits = isl_hash_bits(key_hash, table->bits);
134 size = 1 << table->bits;
135 for (h = key_bits; table->entries[h].data; h = (h+1) % size)
136 if (table->entries[h].hash == key_hash &&
137 eq(table->entries[h].data, val))
138 return &table->entries[h];
140 if (!reserve)
141 return NULL;
143 if (4 * table->n >= 3 * size) {
144 if (grow_table(ctx, table, eq) < 0)
145 return NULL;
146 return isl_hash_table_find(ctx, table, key_hash, eq, val, 1);
149 table->n++;
150 table->entries[h].hash = key_hash;
152 return &table->entries[h];
155 int isl_hash_table_foreach(struct isl_ctx *ctx,
156 struct isl_hash_table *table,
157 int (*fn)(void *entry))
159 size_t size;
160 uint32_t h;
162 size = 1 << table->bits;
163 for (h = 0; h < size; ++ h)
164 if (table->entries[h].data && fn(table->entries[h].data) < 0)
165 return -1;
167 return 0;
170 void isl_hash_table_remove(struct isl_ctx *ctx,
171 struct isl_hash_table *table,
172 struct isl_hash_table_entry *entry)
174 int h, h2;
175 size_t size;
177 if (!table || !entry)
178 return;
180 size = 1 << table->bits;
181 h = entry - table->entries;
182 isl_assert(ctx, h >= 0 && h < size, return);
184 for (h2 = h+1; table->entries[h2 % size].data; h2++) {
185 uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash,
186 table->bits);
187 uint32_t offset = (size + bits - (h+1)) % size;
188 if (offset <= h2 - (h+1))
189 continue;
190 *entry = table->entries[h2 % size];
191 h = h2;
192 entry = &table->entries[h % size];
195 entry->hash = 0;
196 entry->data = NULL;
197 table->n--;