~ubuntu-branches/ubuntu/precise/code-saturne/precise

« back to all changes in this revision

Viewing changes to src/mei/mei_hash_table.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2011-11-01 17:43:32 UTC
  • mto: (6.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20111101174332-tl4vk45no0x3emc3
Tags: upstream-2.1.0
ImportĀ upstreamĀ versionĀ 2.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*!
 
2
 * \file mei_hash_table.c
 
3
 *
 
4
 * \brief Hash table, intended to provide a symbol table
 
5
 */
 
6
 
 
7
/*
 
8
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
9
 
 
10
  Copyright (C) 1998-2011 EDF S.A.
 
11
 
 
12
  This program is free software; you can redistribute it and/or modify it under
 
13
  the terms of the GNU General Public License as published by the Free Software
 
14
  Foundation; either version 2 of the License, or (at your option) any later
 
15
  version.
 
16
 
 
17
  This program is distributed in the hope that it will be useful, but WITHOUT
 
18
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
19
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
20
  details.
 
21
 
 
22
  You should have received a copy of the GNU General Public License along with
 
23
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
24
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
25
*/
 
26
 
 
27
/*----------------------------------------------------------------------------*/
 
28
 
 
29
#ifdef __cplusplus
 
30
extern "C" {
 
31
#endif /* __cplusplus */
 
32
 
 
33
/*----------------------------------------------------------------------------
 
34
 * Standard C library headers
 
35
 *----------------------------------------------------------------------------*/
 
36
 
 
37
#include <stdio.h>
 
38
#include <string.h>
 
39
#include <math.h>
 
40
 
 
41
/*----------------------------------------------------------------------------
 
42
 * BFT library headers
 
43
 *----------------------------------------------------------------------------*/
 
44
 
 
45
#include <bft_mem.h>
 
46
#include <bft_error.h>
 
47
 
 
48
/*----------------------------------------------------------------------------
 
49
 * Local headers
 
50
 *----------------------------------------------------------------------------*/
 
51
 
 
52
#include "mei_math_util.h"
 
53
 
 
54
/*----------------------------------------------------------------------------
 
55
 * Header for the current file
 
56
 *----------------------------------------------------------------------------*/
 
57
 
 
58
#include "mei_hash_table.h"
 
59
 
 
60
/*============================================================================
 
61
 * Private function definitions
 
62
 *============================================================================*/
 
63
 
 
64
/*!
 
65
 * \brief Hash function.
 
66
 *
 
67
 * \param [in] s key
 
68
 * \param [in] modulo internal parameter for hash table
 
69
 *
 
70
 * \return value associated to the key s
 
71
 */
 
72
 
 
73
static unsigned
 
74
_hash(const char *const s, const int modulo)
 
75
{
 
76
  unsigned h = 0;
 
77
  int i;
 
78
 
 
79
  for (i = 0; s[i] != '\0'; i++) {
 
80
    h = h*256 + (unsigned) s[i];
 
81
    if (h >= (unsigned) modulo)
 
82
      h %= modulo;
 
83
  }
 
84
  return h;
 
85
}
 
86
 
 
87
/*----------------------------------------------------------------------------
 
88
 *  Allocation d'une struct item
 
89
 *----------------------------------------------------------------------------*/
 
90
 
 
91
static struct item*
 
92
_new_item(const char *const key)
 
93
{
 
94
  struct item* new;
 
95
 
 
96
  /* Allocate item proper */
 
97
  BFT_MALLOC(new, 1, struct item);
 
98
  if (new == NULL)
 
99
    bft_error(__FILE__, __LINE__, 0,
 
100
              "Error in memory allocation\n");
 
101
 
 
102
  /* Allocate memory for string */
 
103
  BFT_MALLOC(new->key, strlen(key)+1, char);
 
104
  if (new->key == NULL)
 
105
    bft_error(__FILE__, __LINE__, 0,
 
106
              "Error in memory allocation\n");
 
107
 
 
108
  BFT_MALLOC(new->data, 1, data_t);
 
109
  if (new->data == NULL)
 
110
    bft_error(__FILE__, __LINE__, 0,
 
111
              "Error in memory allocation\n");
 
112
 
 
113
  return new;
 
114
}
 
115
 
 
116
 
 
117
/*============================================================================
 
118
 *  Fonctions publiques
 
119
 *============================================================================*/
 
120
 
 
121
 
 
122
/*----------------------------------------------------------------------------
 
123
 *  Fonction qui alloue une table de hachage
 
124
 *----------------------------------------------------------------------------*/
 
125
 
 
126
/* Initialize the hash table to the size (modulo) asked for.
 
127
 * Allocates space for the correct number of pointers and sets them to NULL.
 
128
 * If it can't allocate sufficient memory, signals error by setting the size
 
129
 * of the table to 0.
 
130
 */
 
131
 
 
132
void
 
133
mei_hash_table_create(hash_table_t *const htable, const int modulo)
 
134
{
 
135
  int i;
 
136
 
 
137
  /* htable length and record number */
 
138
  htable->n_inter = 0;
 
139
  htable->length  = modulo;
 
140
  htable->record  = 0;
 
141
  htable->table   = NULL;
 
142
 
 
143
  /* htable memory allocation */
 
144
  BFT_MALLOC(htable->table, modulo, struct item*);
 
145
  if (htable->table == NULL) {
 
146
    htable->length = 0;
 
147
    bft_error(__FILE__, __LINE__, 0,
 
148
              "Error in memory allocation\n");
 
149
  }
 
150
 
 
151
  /*htable default initialization: at the beginning all lists are empty */
 
152
  for (i = 0; i < modulo; i++)
 
153
    htable->table[i] = NULL;
 
154
}
 
155
 
 
156
 
 
157
/*----------------------------------------------------------------------------
 
158
 * Insert an element in a hash table
 
159
 *
 
160
 * If the element is already present in the hash table, the pointer
 
161
 * to it is returned. Otherwise, a new element is added, and a pointer
 
162
 * to that element is added.
 
163
 *----------------------------------------------------------------------------*/
 
164
 
 
165
struct item*
 
166
mei_hash_table_find(hash_table_t *const htable, const char *const key)
 
167
{
 
168
  unsigned v;
 
169
  struct item* l;
 
170
  struct item* p;
 
171
 
 
172
  /* List where the string is to be found */
 
173
  v = _hash(key, htable->length);
 
174
  l = htable->table[v];
 
175
 
 
176
  /* Parcours de la liste */
 
177
  for ( p = l; p != 0; p = p->next)
 
178
    if (strcmp(p->key, key) == 0) return p;
 
179
 
 
180
  return NULL;
 
181
}
 
182
 
 
183
 
 
184
/*----------------------------------------------------------------------------
 
185
 * Insertion d'un identificateur dans une table
 
186
 *----------------------------------------------------------------------------*/
 
187
 
 
188
void
 
189
mei_hash_table_insert(hash_table_t *const htable,
 
190
                      const char *const  key,
 
191
                      const mei_flag_t type,
 
192
                      const double value,
 
193
                      const func1_t f1,
 
194
                      const func2_t f2,
 
195
                      const func3_t f3,
 
196
                      const func4_t f4)
 
197
{
 
198
  unsigned v;
 
199
  struct item* item = mei_hash_table_find(htable, key);
 
200
 
 
201
  if (item == NULL) {
 
202
 
 
203
    /* The string was not found. Create a new item to insert it */
 
204
    item = _new_item(key);
 
205
 
 
206
    item->type = type;
 
207
    if (type == FUNC1) {
 
208
      item->data->func = f1;
 
209
 
 
210
    } else if (type == FUNC2) {
 
211
      item->data->f2 = f2;
 
212
 
 
213
    } else if (type == FUNC3) {
 
214
      bft_error(__FILE__, __LINE__, 0, "not implemented yet \n");
 
215
 
 
216
    } else if (type == FUNC4) {
 
217
      bft_error(__FILE__, __LINE__, 0, "not implemented yet \n");
 
218
 
 
219
    } else {
 
220
      item->data->value = value;
 
221
    }
 
222
    strcpy(item->key, key);
 
223
 
 
224
    htable->record++;
 
225
 
 
226
    /* Insert a cell at the head of a list */
 
227
    v = _hash(key, htable->length);
 
228
    item->next = htable->table[v];
 
229
    htable->table[v]= item;
 
230
  }
 
231
  else {
 
232
    item->data->value = value;
 
233
  }
 
234
}
 
235
 
 
236
 
 
237
/*----------------------------------------------------------------------------
 
238
 *
 
239
 *----------------------------------------------------------------------------*/
 
240
 
 
241
 
 
242
struct item*
 
243
mei_hash_table_lookup(hash_table_t *const htable, const char *const key)
 
244
{
 
245
  unsigned v;
 
246
  struct item *item, *next;   /* Pointers to current and next record
 
247
                               * while traversing hash table bucket.  */
 
248
 
 
249
  v = _hash(key, htable->length);
 
250
 
 
251
  /* Lookup for name in hash table bucket corresponding to above hash value. */
 
252
 
 
253
  item = htable->table[v];
 
254
 
 
255
  while (item) {
 
256
    next = item->next;
 
257
    if (!strcmp(item->key, key)) return item;
 
258
    item = next;
 
259
  }
 
260
 
 
261
  return NULL;
 
262
}
 
263
 
 
264
 
 
265
/*----------------------------------------------------------------------------
 
266
 *  Destruction de la table de hachage
 
267
 *----------------------------------------------------------------------------*/
 
268
 
 
269
 
 
270
void
 
271
mei_hash_table_free(hash_table_t *const htable)
 
272
{
 
273
  int i;
 
274
  struct item *item, *next;   /* Pointers to current and next record
 
275
                               * while traversing hash table bucket.  */
 
276
 
 
277
  if (htable == NULL) return;
 
278
 
 
279
  /* Delete hash table as well as data structure representing symbol table. */
 
280
  for (i = 0; i < htable->length; i++) {
 
281
 
 
282
    item = htable->table[i];
 
283
 
 
284
    while (item) {
 
285
      next = item->next;
 
286
      BFT_FREE(item->key);
 
287
      BFT_FREE(item->data);
 
288
      BFT_FREE(item);
 
289
      item = next;
 
290
    }
 
291
  }
 
292
  BFT_FREE(htable->table);
 
293
}
 
294
 
 
295
 
 
296
/*----------------------------------------------------------------------------
 
297
 *  Fonction qui initialise la table de hachage
 
298
 *----------------------------------------------------------------------------*/
 
299
 
 
300
 
 
301
void
 
302
mei_hash_table_init(hash_table_t *const htable)
 
303
{
 
304
  int i, j;
 
305
 
 
306
  /* predefined constants names*/
 
307
  static const char *constants_names[] = { "e", "pi" };
 
308
 
 
309
  /* predefined constants values */
 
310
  static const double constants[] = {2.7182818284590452354, 3.14159265358979323846};
 
311
 
 
312
  /* predefined functions names with one arguments*/
 
313
  static const char *functions_names[] = { "exp",  "log",   "sqrt",
 
314
                                           "sin",  "cos",   "tan",
 
315
                                           "asin", "acos",  "atan",
 
316
                                           "sinh", "cosh",  "tanh",
 
317
                                           "abs" , "int" };
 
318
 
 
319
  /* predefined functions pointers to functions to calculate them */
 
320
  static double (*functions[]) (double) = { exp,  log,  sqrt,
 
321
                                            sin,  cos,  tan,
 
322
                                            asin, acos, atan,
 
323
                                            sinh, cosh, tanh,
 
324
                                            fabs, floor };
 
325
 
 
326
  /* predefined functions names with two arguments*/
 
327
  static const char *functions2_names[] = { "atan2", "min", "max", "mod" };
 
328
 
 
329
  /* predefined functions pointers to functions to calculate them */
 
330
  static double (*functions2[]) (double, double) = { atan2, mei_min, mei_max, fmod };
 
331
 
 
332
 
 
333
  j = sizeof(constants_names) / sizeof(constants_names[0]);
 
334
  for (i = 0; i < j; i++)
 
335
    mei_hash_table_insert(htable,
 
336
                          constants_names[i],
 
337
                          CONSTANT,
 
338
                          constants[i],
 
339
                          NULL,
 
340
                          NULL,
 
341
                          NULL,
 
342
                          NULL);
 
343
 
 
344
  j = sizeof(functions_names) / sizeof(functions_names[0]);
 
345
  for (i = 0; i < j; i++)
 
346
    mei_hash_table_insert(htable,
 
347
                          functions_names[i],
 
348
                          FUNC1,
 
349
                          0,
 
350
                          functions[i],
 
351
                          NULL,
 
352
                          NULL,
 
353
                          NULL);
 
354
 
 
355
  j = sizeof(functions2_names) / sizeof(functions2_names[0]);
 
356
  for (i = 0; i < j; i++)
 
357
    mei_hash_table_insert(htable,
 
358
                          functions2_names[i],
 
359
                          FUNC2,
 
360
                          0,
 
361
                          NULL,
 
362
                          functions2[i],
 
363
                          NULL,
 
364
                          NULL);
 
365
}
 
366
 
 
367
 
 
368
/*----------------------------------------------------------------------------
 
369
 *  Impression des item de la table de hachage pour debugage
 
370
 *----------------------------------------------------------------------------*/
 
371
 
 
372
 
 
373
void
 
374
mei_hash_table_item_print(struct item *item)
 
375
{
 
376
  /* Affichage d'une liste */
 
377
  while (item != NULL) {
 
378
    printf("%s -> %i \n", item->key, item->type);
 
379
    if (item->type != FUNC1 && item->type != FUNC2 && item->type != FUNC3  && item->type != FUNC4)
 
380
      printf("valeur : %f\n", item->data->value);
 
381
    item = item->next;
 
382
  }
 
383
}
 
384
 
 
385
 
 
386
/*----------------------------------------------------------------------------
 
387
 * Dump of table contents for debuging purpose
 
388
 *----------------------------------------------------------------------------*/
 
389
 
 
390
 
 
391
void
 
392
mei_hash_table_dump(hash_table_t *const htable)
 
393
{
 
394
  int i;
 
395
  for (i = 0; i < htable->length; i++) {
 
396
    if (htable->table[i] != NULL) {
 
397
      printf("Entry %d \n", i);
 
398
      mei_hash_table_item_print(htable->table[i]);
 
399
    }
 
400
  }
 
401
}
 
402
 
 
403
 
 
404
/*============================================================================
 
405
 * Test
 
406
 *============================================================================*/
 
407
 
 
408
 
 
409
#undef _TEST_
 
410
#ifdef _TEST_
 
411
 
 
412
int
 
413
main_test(int argc, char *argv[])
 
414
{
 
415
#define HASHSIZE 701 // Modulo by default for hash tables (101, 211, 701,...)
 
416
  hash_table_t htable;
 
417
  struct item *item;
 
418
  char *toto = "pi";
 
419
  printf("Hash Table Testing\n");
 
420
 
 
421
  mei_hash_table_create(&htable, HASHSIZE);
 
422
  mei_hash_table_init(&htable);
 
423
  mei_hash_table_dump(&htable);
 
424
  item = mei_hash_table_lookup(&htable, toto);
 
425
  if (item) mei_hash_table_item_print(item);
 
426
  mei_hash_table_free(&htable);
 
427
 
 
428
  return 0;
 
429
}
 
430
 
 
431
#endif
 
432
 
 
433
 
 
434
#ifdef __cplusplus
 
435
}
 
436
#endif /* __cplusplus */
 
437