- hash functions reviewed and optimzed

This commit is contained in:
2011-01-06 12:05:20 +00:00
parent a6ef33d66c
commit 54aaf846e7
11 changed files with 182 additions and 199 deletions
+6 -2
View File
@@ -7,10 +7,14 @@
#define H5_CORE_API_RETURN(retval) \
\
goto exit; \
exit: \
goto done; \
done: \
return (retval); \
#define H5_GOTO_DONE( ret_val) \
ret_value = ret_val; \
goto done; \
/* WARNING! Changing these values will alter the data model and introduce
* file incompatibilities with previous versions. */
#define H5_DATANAME_LEN 64
+89 -63
View File
@@ -65,11 +65,15 @@ h5priv_hcreate (
size_t nel,
h5_hashtable_t* htab,
int (*compare)(const void*, const void*),
unsigned int (*compute_hash)(const void*)
unsigned int (*compute_hash)(const void*),
h5_err_t (*free_entry)(h5_file_t* const f, const void*)
) {
H5_CORE_API_ENTER;
h5_err_t h5err = H5_SUCCESS;
/* Test for correct arguments. */
if (htab == NULL || htab->table != NULL) {
return h5_error_internal (f, __FILE__, __func__, __LINE__);
TRY2( h5_error_internal (f, __FILE__, __func__, __LINE__) );
}
/* Change nel to the first prime number not smaller as nel. */
nel |= 1; /* make odd */
@@ -80,13 +84,14 @@ h5priv_hcreate (
htab->filled = 0;
htab->compare = compare;
htab->compute_hash = compute_hash;
htab->free_entry = free_entry;
/* allocate memory and zero out */
TRY( (htab->table = (_ENTRY *) h5_calloc (
TRY2( (htab->table = (_ENTRY *) h5_calloc (
f, htab->size + 1, sizeof (_ENTRY))) );
/* everything went alright */
return H5_SUCCESS;
H5_CORE_API_RETURN (h5err);
}
/*
@@ -98,8 +103,10 @@ h5priv_hresize (
size_t nel, // number of entries to grow
h5_hashtable_t* htab // hash table to resize
) {
H5_CORE_API_ENTER;
h5_err_t h5err = H5_SUCCESS;
if (htab == NULL || htab->table == NULL) {
return h5_error_internal (f, __FILE__, __func__, __LINE__);
TRY2( h5_error_internal (f, __FILE__, __func__, __LINE__) );
}
// create new hash table
h5_hashtable_t __htab;
@@ -107,28 +114,47 @@ h5priv_hresize (
nel += htab->size;
h5_debug (f, "Resize hash table from %u to %lu elements.",
htab->size, nel);
TRY( h5priv_hcreate (
f, nel, &__htab, htab->compare, htab->compute_hash) );
TRY2( h5priv_hcreate (f, nel, &__htab, htab->compare,
htab->compute_hash, htab->free_entry) );
// add all entries to new hash table
unsigned int idx;
for (idx = 1; idx <= htab->size; idx++) {
if (htab->table[idx].used) {
void* ventry;
h5priv_hsearch (
TRY2( h5priv_hsearch (
f,
htab->table[idx].entry,
H5_ENTER,
&ventry,
&__htab);
&__htab) );
}
}
// destroy old hash table
TRY (h5priv_hdestroy (f, htab) );
/* Free used memory. */
TRY2( h5_free (f, htab->table) );
/* the sign for an existing table is an value != NULL in htable */
htab->table = NULL;
*htab = __htab;
H5_CORE_API_RETURN (h5err);
}
static inline h5_err_t
hwalk (
h5_file_t* const f,
struct hsearch_data* htab,
h5_err_t (*visit)(h5_file_t*const f, const void *item)
) {
unsigned int idx = 1;
for (idx = 1; idx < htab->size; idx++) {
if (htab->table[idx].used) {
TRY( (*visit)(f, &htab->table[idx].entry) );
}
}
return H5_SUCCESS;
}
/* After using the hash table it has to be destroyed. The used memory can
be freed and the local static variable can be marked as not used. */
h5_err_t
@@ -136,17 +162,21 @@ h5priv_hdestroy (
h5_file_t* const f,
struct hsearch_data* htab
) {
H5_CORE_API_ENTER;
h5_err_t ret_value = H5_SUCCESS;
/* Test for correct arguments. */
if (htab == NULL) {
return h5_error_internal (f, __FILE__, __func__, __LINE__);
TRY2( h5_error_internal (f, __FILE__, __func__, __LINE__) );
}
TRY2( hwalk (f, htab, htab->free_entry) );
/* Free used memory. */
TRY( h5_free (f, htab->table) );
TRY2( h5_free (f, htab->table) );
/* the sign for an existing table is an value != NULL in htable */
htab->table = NULL;
return H5_SUCCESS;
H5_CORE_API_RETURN (ret_value);
}
@@ -172,6 +202,8 @@ h5priv_hsearch (
void** retval,
struct hsearch_data* htab
) {
H5_CORE_API_ENTER;
h5_err_t ret_value = H5_SUCCESS;
unsigned int hval;
unsigned int idx;
@@ -189,7 +221,7 @@ h5priv_hsearch (
if (retval) {
*retval = htab->table[idx].entry;
}
return H5_SUCCESS;
H5_GOTO_DONE (H5_SUCCESS);
}
/* Second hash function, as suggested in [Knuth] */
@@ -216,7 +248,7 @@ h5priv_hsearch (
if (retval) {
*retval = htab->table[idx].entry;
}
return H5_SUCCESS;
H5_GOTO_DONE (H5_SUCCESS);
}
} while (htab->table[idx].used);
}
@@ -230,7 +262,7 @@ h5priv_hsearch (
if (retval) {
*retval = NULL;
}
return H5_ERR;
H5_GOTO_DONE (H5_ERR);
}
htab->table[idx].used = hval;
@@ -241,30 +273,16 @@ h5priv_hsearch (
if (retval) {
*retval = htab->table[idx].entry;
}
return H5_SUCCESS;
H5_GOTO_DONE (H5_SUCCESS);
} else if (action == H5_REMOVE) {
htab->table[idx].used = 0; /* mark as unused, but */
*retval = htab->table[idx].entry; /* return ptr to entry */
return H5_SUCCESS;
H5_GOTO_DONE (H5_SUCCESS);
}
*retval = NULL;
if (retval) *retval = NULL;
h5_debug (f, "Key not found in hash table.");
return H5_NOK;
}
h5_err_t
h5priv_hwalk (
h5_file_t* const f,
struct hsearch_data* htab,
h5_err_t (*visit)(h5_file_t*const f, const void *item)
) {
unsigned int idx = 1;
for (idx = 1; idx < htab->size; idx++) {
if (htab->table[idx].used) {
TRY( (*visit)(f, &htab->table[idx].entry) );
}
}
return H5_SUCCESS;
ret_value = H5_NOK;
H5_CORE_API_RETURN (ret_value);
}
typedef struct {
@@ -272,7 +290,7 @@ typedef struct {
} h5_hitem_string_keyed_t;
static int
_hcmp_string_keyed (
cmp_string_keyed (
const void* __a,
const void* __b
) {
@@ -282,38 +300,55 @@ _hcmp_string_keyed (
}
static unsigned int
_hcompute_string_keyed (
const void* __item
compute_string_keyed (
const void* __entry
) {
h5_hitem_string_keyed_t* item = (h5_hitem_string_keyed_t*) __item;
unsigned int len = strlen (item->key);
h5_hitem_string_keyed_t* entry = (h5_hitem_string_keyed_t*) __entry;
unsigned int len = strlen (entry->key);
unsigned int hval = len;
unsigned int count = len;
while (count-- > 0) {
hval <<= 4;
hval += item->key[count];
hval += entry->key[count];
}
return hval;
}
static h5_err_t
free_string_keyed (
h5_file_t* const f,
const void* __entry
) {
h5_hitem_string_keyed_t* entry = (h5_hitem_string_keyed_t*) __entry;
TRY( h5_free (f, entry->key) );
TRY( h5_free (f, entry) );
return H5_SUCCESS;
}
h5_err_t
h5priv_hcreate_string_keyed (
h5_file_t* const f,
size_t nel,
h5_hashtable_t* htab
h5_hashtable_t* htab,
h5_err_t (*free_entry)(h5_file_t* const f, const void*)
) {
return h5priv_hcreate (f, nel, htab,
_hcmp_string_keyed, _hcompute_string_keyed);
}
static int
hcmp_loc_id_keyed (
const void* __a,
const void* __b
) {
return memcmp (__a, __b, sizeof(h5_loc_id_t));
H5_CORE_API_ENTER;
h5_err_t ret_value = H5_SUCCESS;
if (free_entry == NULL) {
TRY2( ret_value = h5priv_hcreate (f, nel, htab,
cmp_string_keyed,
compute_string_keyed,
free_string_keyed) );
} else {
TRY2( ret_value = h5priv_hcreate (f, nel, htab,
cmp_string_keyed,
compute_string_keyed,
free_entry) );
}
H5_CORE_API_RETURN (ret_value);
}
#if 0
static unsigned int
hcompute_loc_id_keyed (
const void*__item
@@ -330,13 +365,4 @@ hcompute_loc_id_keyed (
}
return hval;
}
h5_err_t
h5priv_hcreate_loc_id_keyed (
h5_file_t* const f,
size_t nel,
h5_hashtable_t* htab
) {
return h5priv_hcreate (f, nel, htab,
hcmp_loc_id_keyed, hcompute_loc_id_keyed);
}
#endif
+5 -16
View File
@@ -7,6 +7,7 @@ typedef struct hsearch_data {
unsigned int filled;
int (*compare)(const void*, const void*);
unsigned int (*compute_hash)(const void*);
h5_err_t (*free_entry)(h5_file_t* const f, const void*);
} h5_hashtable_t;
/* Action which shall be performed in the call to hsearch. */
@@ -37,7 +38,8 @@ h5priv_hcreate (
size_t __nel,
h5_hashtable_t* __htab,
int (*compare)(const void*, const void*),
unsigned int (*compute_hash)(const void*)
unsigned int (*compute_hash)(const void*),
h5_err_t (*free_entry)(h5_file_t* const f, const void*)
);
extern h5_err_t
@@ -53,25 +55,12 @@ h5priv_hdestroy (
h5_hashtable_t* __htab
);
extern h5_err_t
h5priv_hwalk (
h5_file_t* f,
h5_hashtable_t* __htab,
h5_err_t (*visit)(h5_file_t* const f, const void* __item)
);
extern h5_err_t
h5priv_hcreate_string_keyed (
h5_file_t* const f,
size_t nel,
h5_hashtable_t* htab
);
h5_err_t
h5priv_hcreate_loc_id_keyed (
h5_file_t* const f,
size_t nel,
h5_hashtable_t* htab
h5_hashtable_t* htab,
h5_err_t (*free_entry)(h5_file_t* const f, const void*)
);
#endif
+4 -3
View File
@@ -39,10 +39,11 @@ static inline h5_err_t
grow_idlist (
h5_file_t* const f,
h5_idlist_t** list,
size_t num_items
size_t new_size
) {
size_t size = sizeof (**list) + (num_items-1)*sizeof((*list)->items[0]);
TRY( *list = h5_alloc (f, *list, size) );
size_t bytes_to_allocate = sizeof (**list) + (new_size-1)*sizeof((*list)->items[0]);
TRY( *list = h5_alloc (f, *list, bytes_to_allocate) );
(*list)->size = new_size;
return H5_SUCCESS;
}
+2 -1
View File
@@ -7,7 +7,8 @@ get_loc_elem (
h5_file_t* const f,
const h5_loc_idx_t elem_idx
) {
return (h5_generic_loc_elem_t*)&f->t->loc_elems.tets[elem_idx];
h5_loc_tet_t* elem = &f->t->loc_elems.tets[elem_idx];
return (h5_generic_loc_elem_t*)elem;
}
static h5_loc_idx_t
+10 -32
View File
@@ -20,14 +20,18 @@
static inline h5_err_t
alloc_tv (
h5_file_t* const f
h5_file_t* const f,
const h5t_lvl_idx_t from_lvl
) {
h5t_fdata_t* t = f->t;
h5_loc_idx_t num_vertices = t->num_vertices[t->num_leaf_levels-1];
h5t_adjacencies_t* adj = &t->adjacencies;
// allocate one ID list per vertex
TRY( adj->tv.v = h5_calloc (f, num_vertices, sizeof(*adj->tv.v)) );
// allocate ptr to ID-list per vertex
TRY( adj->tv.v = h5_alloc (f, adj->tv.v, num_vertices*sizeof(*adj->tv.v)) );
size_t i = from_lvl <= 0 ? 0 : t->num_vertices[from_lvl-1];
bzero (adj->tv.v+i, (num_vertices-i)*sizeof(*adj->tv.v));
return H5_SUCCESS;
}
@@ -59,7 +63,7 @@ compute_elems_of_vertices (
const h5t_lvl_idx_t from_lvl
) {
/* expand structure */
TRY( alloc_tv (f) );
TRY( alloc_tv (f, from_lvl) );
/* loop over all elements in current level */
h5t_fdata_t* t = f->t;
@@ -81,24 +85,6 @@ compute_elems_of_vertices (
return H5_SUCCESS;
}
static h5_err_t
free_idlist (
h5_file_t * const f,
const void* __list
) {
h5_idlist_t* list = *(h5_idlist_t**)__list;
TRY( h5priv_free_idlist (f, &list) );
return H5_SUCCESS;
}
static inline h5_err_t
release_te (
h5_file_t* const f
) {
TRY( h5priv_hwalk (f, &f->t->adjacencies.te_hash, free_idlist) );
return H5_SUCCESS;
}
/*
Compute T(E) from current level up to highest levels.
*/
@@ -123,14 +109,6 @@ compute_elems_of_edges (
return H5_SUCCESS;
}
static inline h5_err_t
release_td (
h5_file_t* const f
) {
TRY( h5priv_hwalk (f, &f->t->adjacencies.te_hash, free_idlist) );
return H5_SUCCESS;
}
static inline h5_err_t
compute_elems_of_triangles (
h5_file_t* const f,
@@ -878,8 +856,8 @@ release_internal_structs (
) {
h5t_fdata_t* t = f->t;
TRY( release_tv (f) );
TRY( release_te (f) );
TRY( release_td (f) );
TRY( h5priv_hdestroy (f, &t->adjacencies.te_hash) );
TRY( h5priv_hdestroy (f, &t->adjacencies.td_hash) );
bzero (&t->adjacencies, sizeof (t->adjacencies));
return H5_SUCCESS;
}
+11 -27
View File
@@ -19,14 +19,18 @@
static inline h5_err_t
alloc_tv (
h5_file_t* const f
h5_file_t* const f,
const h5t_lvl_idx_t from_lvl
) {
h5t_fdata_t* t = f->t;
h5_loc_idx_t num_vertices = t->num_vertices[t->num_leaf_levels-1];
h5t_adjacencies_t* adj = &t->adjacencies;
// allocate one ID list per vertex
TRY( adj->tv.v = h5_calloc (f, num_vertices, sizeof(*adj->tv.v)) );
// allocate ptr to ID-list per vertex
TRY( adj->tv.v = h5_alloc (f, adj->tv.v, num_vertices*sizeof(*adj->tv.v)) );
size_t i = from_lvl <= 0 ? 0 : t->num_vertices[from_lvl-1];
bzero (adj->tv.v+i, (num_vertices-i)*sizeof(*adj->tv.v));
return H5_SUCCESS;
}
@@ -57,9 +61,8 @@ compute_elems_of_vertices (
h5_file_t* const f,
const h5t_lvl_idx_t from_lvl
) {
h5_debug (f, "%s (%lld)", __func__, (long long)from_lvl);
/* expand structure */
TRY( alloc_tv (f) );
TRY( alloc_tv (f, from_lvl) );
/* loop over all elements in current level */
h5t_fdata_t *t = f->t;
@@ -74,29 +77,10 @@ compute_elems_of_vertices (
TRY( h5priv_insert_idlist (
f,
&t->adjacencies.tv.v[vidx],
h5tpriv_build_vertex_id (
face_idx, idx), -1) );
h5tpriv_build_vertex_id (face_idx, idx),
-1) );
}
}
h5_debug (f, "%s (%lld): done", __func__, (long long)from_lvl);
return H5_SUCCESS;
}
static h5_err_t
free_idlist (
h5_file_t * const f,
const void* __list
) {
h5_idlist_t* list = *(h5_idlist_t**)__list;
TRY( h5priv_free_idlist (f, &list) );
return H5_SUCCESS;
}
static inline h5_err_t
release_te (
h5_file_t* const f
) {
TRY( h5priv_hwalk (f, &f->t->adjacencies.te_hash, free_idlist) );
return H5_SUCCESS;
}
@@ -535,7 +519,7 @@ release_internal_structs (
) {
h5t_fdata_t *t = f->t;
TRY( release_tv (f) );
TRY( release_te (f) );
TRY( h5priv_hdestroy (f, &t->adjacencies.te_hash) );
bzero (&t->adjacencies, sizeof (t->adjacencies));
return H5_SUCCESS;
}
+33 -24
View File
@@ -30,18 +30,16 @@ compute_te_hashval (
return hval;
}
h5_err_t
h5tpriv_create_te_htab (
h5_file_t* const f,
size_t nel
static h5_err_t
release_te_entry (
h5_file_t * const f,
const void* __entry
) {
h5t_adjacencies_t* a = &f->t->adjacencies;
return h5priv_hcreate (
f,
nel,
&a->te_hash,
cmp_te_entries,
compute_te_hashval);
struct h5_te_entry* entry = *(struct h5_te_entry**)__entry;
h5_idlist_t* list = entry->value;
TRY( h5priv_free_idlist (f, &list) );
TRY( h5_free (f, entry) );
return H5_SUCCESS;
}
h5_err_t
@@ -51,7 +49,13 @@ h5tpriv_resize_te_htab (
) {
h5t_adjacencies_t* a = &f->t->adjacencies;
if ( a->te_hash.size == 0 ) {
TRY( h5tpriv_create_te_htab (f, nel) );
TRY( h5priv_hcreate (
f,
nel,
&a->te_hash,
cmp_te_entries,
compute_te_hashval,
release_te_entry) );
} else if (a->te_hash.size < nel) {
TRY( h5priv_hresize (f, nel, &a->te_hash) );
}
@@ -190,20 +194,19 @@ compute_td_hashval (
return hval;
}
h5_err_t
h5tpriv_create_td_htab (
h5_file_t* const f,
size_t nel
static h5_err_t
release_td_entry (
h5_file_t * const f,
const void* __entry
) {
h5t_adjacencies_t* a = &f->t->adjacencies;
return h5priv_hcreate (
f,
nel,
&a->td_hash,
cmp_td_entries,
compute_td_hashval);
struct h5_td_entry* entry = *(struct h5_td_entry**)__entry;
h5_idlist_t* list = entry->value;
TRY( h5priv_free_idlist (f, &list) );
TRY( h5_free (f, entry) );
return H5_SUCCESS;
}
h5_err_t
h5tpriv_resize_td_htab (
h5_file_t* const f,
@@ -211,7 +214,13 @@ h5tpriv_resize_td_htab (
) {
h5t_adjacencies_t* a = &f->t->adjacencies;
if (a->td_hash.size == 0) {
TRY( h5tpriv_create_td_htab (f, nel) );
TRY( h5priv_hcreate (
f,
nel,
&a->td_hash,
cmp_td_entries,
compute_td_hashval,
release_td_entry) );
} else if (a->td_hash.size < nel) {
TRY( h5priv_hresize (f, nel, &a->td_hash) );
}
-13
View File
@@ -32,12 +32,6 @@ typedef struct h5t_idlisthash_entry {
h5t_idlisthash_key_t key;
} h5t_idlisthash_entry_t;
h5_err_t
h5tpriv_create_te_htab (
h5_file_t * const f,
size_t nel
);
h5_err_t
h5tpriv_resize_te_htab (
h5_file_t * const f,
@@ -67,13 +61,6 @@ h5tpriv_find_te2 (
h5_idlist_t **retval
);
h5_err_t
h5tpriv_create_td_htab (
h5_file_t * const f,
size_t nel
);
h5_err_t
h5tpriv_resize_td_htab (
h5_file_t * const f,
+20 -16
View File
@@ -5,28 +5,16 @@
#include "h5_core_private.h"
/*
To discuss:
TODO:
- read tagsets on demand
*/
/*
Initialize a tag container
*/
static h5_err_t
init_container (
h5_file_t* const f,
const size_t ntags,
h5t_tagcontainer_t* ctn
) {
ctn->names = h5_calloc (f, ntags, sizeof(char*));
TRY( h5priv_hcreate_string_keyed (f, ntags, &ctn->sets));
return H5_SUCCESS;
}
/*
Release a tag-set
*/
static h5_err_t
static inline h5_err_t
release_tagset (
h5_file_t* const f,
h5t_tagset_t* tagset
@@ -57,6 +45,22 @@ release_tagset2 (
return release_tagset (f, tagset);
}
/*
Initialize a tag container
*/
static inline h5_err_t
init_container (
h5_file_t* const f,
const size_t ntags,
h5t_tagcontainer_t* ctn
) {
ctn->names = h5_calloc (f, ntags, sizeof(char*));
TRY( h5priv_hcreate_string_keyed (f, ntags, &ctn->sets,
release_tagset2) );
return H5_SUCCESS;
}
/*
Release all sets in given container
*/
@@ -66,7 +70,7 @@ release_container (
h5t_tagcontainer_t* ctn
) {
if (ctn->num_sets == 0) return H5_SUCCESS;
TRY( h5priv_hwalk (f, &ctn->sets, release_tagset2) );
TRY( h5priv_hdestroy (f, &ctn->sets) );
TRY( h5_free (f, ctn->names) );
memset (ctn, 0, sizeof (*ctn));
return H5_SUCCESS;
+2 -2
View File
@@ -40,7 +40,7 @@ typedef struct h5_glb_tetrahedron {
typedef h5_glb_tetrahedron_t h5_glb_tet_t;
typedef struct h5_loc_tetrahedron {
h5_loc_idx_t glb_idx;
h5_glb_idx_t glb_idx;
h5_loc_idx_t parent_idx;
h5_loc_idx_t child_idx;
h5t_lvl_idx_t level_idx;
@@ -62,7 +62,7 @@ typedef struct h5_generic_loc_elem {
h5_glb_idx_t glb_idx;
h5_loc_idx_t parent_idx;
h5_loc_idx_t child_idx;
h5_int32_t level_idx;
h5t_lvl_idx_t level_idx;
h5t_lvl_idx_t refinement_level;
h5t_elem_flags_t flags;
h5_loc_idx_t indices[1];