Introduce old redir program
[lcapit-junk-code.git] / mega-sena / mod_cuckoo.c
blob032a4a4280bbf87f218494d1850d018aa1b9b6be
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
5 #include "module.h"
6 #include "mod_cuckoo.h"
8 struct cuckoo_array {
9 void **array;
10 unsigned int size;
13 struct cuckoo_tbl {
14 int size;
15 unsigned int positions;
16 struct cuckoo_array first, second;
19 static struct cuckoo_tbl cuckoo_tbl;
21 #define HASH_TABLE_SIZE 3072 /* 3k */
22 #define LOTTERY_MAX 6 /* bytes */
23 #define NAME_LENGTH 17 /* bytes */
25 static inline unsigned int tdb_hash(char *name)
27 unsigned value; /* Used to compute the hash value. */
28 unsigned i; /* Used to cycle through random values. */
30 /* Set the initial value from the key size. */
31 for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)
32 value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
34 return (1103515243 * value + 12345);
37 static inline unsigned int joaat_hash(char *name)
39 int i;
40 unsigned int hash = 0;
42 for (i = 0; i < (int) strlen(name); i++) {
43 hash += name[i];
44 hash += (hash << 10);
45 hash ^= (hash >> 6);
48 hash += (hash << 3);
49 hash ^= (hash >> 11);
50 hash += (hash << 15);
52 return hash;
55 static void cuckoo_print_stats(void)
57 struct cuckoo_tbl *tbl = &cuckoo_tbl;
59 printf("\n-> Hash table statistics\n");
60 printf("First table size: %4d\n", tbl->positions);
61 printf(" o in use: %4d\n", tbl->first.size);
62 printf(" o free: %4d\n", tbl->positions - tbl->first.size);
63 printf("Second table size: %4d\n", tbl->positions);
64 printf(" o in use: %4d\n", tbl->second.size);
65 printf(" o free: %4d\n", tbl->positions - tbl->second.size);
66 printf("\n");
69 static int cuckoo_lookup(char *name, unsigned int *h)
71 unsigned int hash;
73 hash = tdb_hash(name) % cuckoo_tbl.positions;
74 if (cuckoo_tbl.first.array[hash] == NULL)
75 return 0;
77 if (!memcmp(cuckoo_tbl.first.array[hash], name, NAME_LENGTH))
78 goto found;
80 hash = joaat_hash(name) % cuckoo_tbl.positions;
81 if (cuckoo_tbl.second.array[hash] == NULL)
82 return 0;
84 if (!memcmp(cuckoo_tbl.second.array[hash], name, NAME_LENGTH))
85 goto found;
87 return 0;
89 found:
90 if (h)
91 *h = hash;
92 return 1;
95 static int cuckoo_insert(char *name)
97 int ret;
98 void *el, *tmp;
99 unsigned int i, hash;
101 ret = cuckoo_lookup(name, NULL);
102 if (ret) {
103 /* key already exists */
104 return 1;
107 el = (void *) name;
109 for (i = 0; i < cuckoo_tbl.positions; i++) {
111 hash = tdb_hash(el) % cuckoo_tbl.positions;
112 if (cuckoo_tbl.first.array[hash] == NULL) {
113 cuckoo_tbl.first.array[hash] = el;
114 cuckoo_tbl.first.size++;
115 goto out;
118 tmp = cuckoo_tbl.first.array[hash];
119 cuckoo_tbl.first.array[hash] = el;
120 el = tmp;
122 hash = joaat_hash(el) % cuckoo_tbl.positions;
123 if (cuckoo_tbl.second.array[hash] == NULL) {
124 cuckoo_tbl.second.array[hash] = el;
125 cuckoo_tbl.second.size++;
126 goto out;
129 tmp = cuckoo_tbl.second.array[hash];
130 cuckoo_tbl.second.array[hash] = el;
131 el = tmp;
134 fprintf(stderr, "Out of Max loop, aborting\n");
135 abort();
137 out:
138 cuckoo_tbl.size++;
139 return 0;
142 #if 0
143 static struct cuckoo_tbl *rehash(struct cuckoo_tbl *tbl)
145 int err;
146 unsigned int i;
147 struct cuckoo_tbl *new_table;
149 new_table = malloc(sizeof(struct cuckoo_tbl));
150 if (!new_table)
151 return NULL;
153 err = cuckoo_init(new_table, tbl->positions * 2);
154 if (err)
155 goto out_err;
157 for (i = 0; i < tbl->positions; i++) {
158 if (tbl->first.array[i]) {
159 err = cuckoo_insert(new_table,
160 tbl->first.array[i]);
161 if (err)
162 goto out_err;
165 if (tbl->second.array[i]) {
166 err = cuckoo_insert(new_table,
167 tbl->second.array[i]);
168 if (err)
169 goto out_err;
173 cuckoo_destroy(tbl);
174 free(tbl);
176 return new_table;
178 out_err:
179 free(new_table);
180 return NULL;
182 #endif
184 static int cuckoo_init(void)
186 int i;
187 const int positions = HASH_TABLE_SIZE;
189 cuckoo_tbl.first.array = malloc(sizeof(void *) * positions);
190 if (!cuckoo_tbl.first.array)
191 return -1;
193 cuckoo_tbl.second.array = malloc(sizeof(void *) * positions);
194 if (!cuckoo_tbl.second.array) {
195 free(cuckoo_tbl.first.array);
196 return -1;
199 for (i = 0; i < positions; i++)
200 cuckoo_tbl.first.array[i] = cuckoo_tbl.second.array[i] = NULL;
202 cuckoo_tbl.positions = positions;
203 cuckoo_tbl.size = cuckoo_tbl.first.size = cuckoo_tbl.second.size = 0;
205 return 0;
208 static void cuckoo_destroy(void)
210 unsigned int i;
212 for (i = 0; i < cuckoo_tbl.positions; i++) {
213 if (cuckoo_tbl.first.array[i])
214 free(cuckoo_tbl.first.array[i]);
216 if (cuckoo_tbl.second.array[i])
217 free(cuckoo_tbl.second.array[i]);
220 free(cuckoo_tbl.first.array);
221 free(cuckoo_tbl.second.array);
224 struct module cuckoo_module = {
225 .mod_name = "Cuckoo hashing",
226 .mod_init = cuckoo_init,
227 .mod_insert = cuckoo_insert,
228 .mod_lookup = cuckoo_lookup,
229 .mod_destroy = cuckoo_destroy,
230 .mod_stats = cuckoo_print_stats,