From: Mike D. Lowis Date: Thu, 1 Oct 2015 20:01:56 +0000 (-0400) Subject: Added some hash functions to the hashtable interface X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=250d10a2eb71c18b3c25d89651d48f37c215a7c8;p=archive%2Fcarl.git Added some hash functions to the hashtable interface --- diff --git a/source/data/hash.c b/source/data/hash.c index 7fadd12..67388b5 100644 --- a/source/data/hash.c +++ b/source/data/hash.c @@ -53,6 +53,37 @@ static void rehash(hash_t* hash) } } +uint32_t hash_bytes(uint8_t* key, size_t len) +{ + uint32_t a=31415u, b=27183u, hash; + for (hash=0; len > 0; key++, len--, a*=b) + hash = (a * hash) + *key; + return hash32(hash); +} + +uint64_t hash64(uint64_t key) +{ + key = (~key) + (key << 21); // key = (key << 21) - key - 1; + key = key ^ (key >> 24); + key = (key + (key << 3)) + (key << 8); // key * 265 + key = key ^ (key >> 14); + key = (key + (key << 2)) + (key << 4); // key * 21 + key = key ^ (key >> 28); + key = key + (key << 31); + return key; +} + +uint32_t hash32(uint32_t key) +{ + key = (key+0x7ed55d16) + (key<<12); + key = (key^0xc761c23c) ^ (key>>19); + key = (key+0x165667b1) + (key<<5); + key = (key+0xd3a2646c) ^ (key<<9); + key = (key+0xfd7046c5) + (key<<3); + key = (key^0xb55a4f09) ^ (key>>16); + return key; +} + void hash_init(hash_t* hash, hash_hashfn_t hashfn, hash_cmpfn_t cmpfn, hash_freefn_t delfn) { hash->size = 0; diff --git a/source/data/hash.h b/source/data/hash.h index 0c9f54f..f720b57 100644 --- a/source/data/hash.h +++ b/source/data/hash.h @@ -7,6 +7,7 @@ #include #include +#include typedef struct hash_entry_t { unsigned int hash; @@ -28,6 +29,12 @@ typedef struct { hash_freefn_t delfn; } hash_t; +uint32_t hash_bytes(uint8_t* key, size_t len); + +uint64_t hash64(uint64_t key); + +uint32_t hash32(uint32_t a); + void hash_init(hash_t* hash, hash_hashfn_t hashfn, hash_cmpfn_t cmpfn, hash_freefn_t delfn); void hash_deinit(hash_t* hash); diff --git a/tests/data/hash.c b/tests/data/hash.c index e77a43f..522afd9 100644 --- a/tests/data/hash.c +++ b/tests/data/hash.c @@ -5,6 +5,8 @@ #include #include +static const uint Num_Iterations = 1000000; + typedef struct { hash_entry_t link; uint val; @@ -34,10 +36,9 @@ static void delete_func(hash_entry_t* entry) TEST_SUITE(Hash) { TEST(Verify sequential hash inserts and lookups) { - uint maxval = 1000000; hash_t hash; hash_init(&hash, hash_func, compare_func, delete_func); - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); entry->val = i; @@ -45,7 +46,7 @@ TEST_SUITE(Hash) { CHECK(i+1 == hash_size(&hash)); CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); } - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t search = { .val = i }; hash_entry_t* entry = hash_get(&hash, &(search.link)); @@ -59,10 +60,9 @@ TEST_SUITE(Hash) { TEST(Verify ping pong hash inserts and lookups) { - uint maxval = 1000000; hash_t hash; hash_init(&hash, hash_func, compare_func, delete_func); - for (uint i = 0; i < (maxval/2); i++) { + for (uint i = 0; i < (Num_Iterations/2); i++) { /* Insert the lower number */ int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); entry->val = i; @@ -70,11 +70,11 @@ TEST_SUITE(Hash) { CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); /* Insert the higher number */ entry = (int_node_t*)malloc(sizeof(int_node_t)); - entry->val = maxval - i; + entry->val = Num_Iterations - i; hash_set(&hash, &(entry->link)); CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); } - for (uint i = 0; i < (maxval/2); i++) + for (uint i = 0; i < (Num_Iterations/2); i++) { /* Find the lower number */ int_node_t search = { .val = i }; @@ -83,7 +83,7 @@ TEST_SUITE(Hash) { CHECK(entry != NULL); CHECK(search.val == ientry->val); /* Find the higher number */ - search.val = maxval-i; + search.val = Num_Iterations-i; entry = hash_get(&hash, &(search.link)); ientry = container_of(entry, int_node_t, link); CHECK(entry != NULL); @@ -108,10 +108,9 @@ TEST_SUITE(Hash) { TEST(Verify sequential inserts and deletions) { - uint maxval = 1000000; hash_t hash; hash_init(&hash, hash_func, compare_func, delete_func); - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); entry->val = i; @@ -119,43 +118,41 @@ TEST_SUITE(Hash) { CHECK(i+1 == hash_size(&hash)); CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); } - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t search = { .val = i }; CHECK(hash_del(&hash, &(search.link))); - CHECK((maxval - (i+1)) == hash_size(&hash)); + CHECK((Num_Iterations - (i+1)) == hash_size(&hash)); } hash_deinit(&hash); } TEST(Verify reverse inserts and deletions) { - uint maxval = 1000000; hash_t hash; hash_init(&hash, hash_func, compare_func, delete_func); - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); - entry->val = maxval - i; + entry->val = Num_Iterations - i; hash_set(&hash, &(entry->link)); CHECK(i+1 == hash_size(&hash)); CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); } - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t search = { .val = i+1 }; CHECK(hash_del(&hash, &(search.link))); - CHECK((maxval - (i+1)) == hash_size(&hash)); + CHECK((Num_Iterations - (i+1)) == hash_size(&hash)); } hash_deinit(&hash); } TEST(Verify ping pong hash inserts and deletions) { - uint maxval = 1000000; hash_t hash; hash_init(&hash, hash_func, compare_func, delete_func); - for (uint i = 0; i < (maxval/2); i++) { + for (uint i = 0; i < (Num_Iterations/2); i++) { /* Insert the lower number */ int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); entry->val = i; @@ -163,11 +160,11 @@ TEST_SUITE(Hash) { CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); /* Insert the higher number */ entry = (int_node_t*)malloc(sizeof(int_node_t)); - entry->val = maxval - i; + entry->val = Num_Iterations - i; hash_set(&hash, &(entry->link)); CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); } - for (uint i = 0; i < maxval; i++) + for (uint i = 0; i < Num_Iterations; i++) { int_node_t search = { .val = i }; if (hash_get(&hash, &(search.link)))