Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 3 commits
  • 6 files changed
  • 0 commit comments
  • 1 contributor
Showing with 160 additions and 175 deletions.
  1. +1 −3 src/lcthw/hashmap.c
  2. +52 −0 src/lcthw/hashmap_algos.c
  3. +12 −0 src/lcthw/hashmap_algos.h
  4. +32 −86 src/lcthw/radixmap.c
  5. +63 −0 tests/hashmap_algos_tests.c
  6. +0 −86 tests/radixmap_tests.c
View
4 src/lcthw/hashmap.c
@@ -10,7 +10,7 @@ static int default_compare(void *a, void *b)
}
/**
- * Simple Bob Jenkin's hash algorithm taken from the
+ * Simple Bob Jenkins's hash algorithm taken from the
* wikipedia description.
*/
static uint32_t default_hash(void *a)
@@ -62,7 +62,6 @@ void Hashmap_destroy(Hashmap *map)
int i = 0;
int j = 0;
- // TODO: pack up this double-for-loop pattern into a macro somehow
if(map) {
if(map->buckets) {
for(i = 0; i < DArray_count(map->buckets); i++) {
@@ -131,7 +130,6 @@ int Hashmap_set(Hashmap *map, void *key, void *data)
HashmapNode *node = Hashmap_node_create(hash, key, data);
check_mem(node);
- // TODO: do sorting on the darray to make finding faster by the hash+key
DArray_push(bucket, node);
return 0;
View
52 src/lcthw/hashmap_algos.c
@@ -0,0 +1,52 @@
+#include <lcthw/hashmap_algos.h>
+#include <lcthw/bstrlib.h>
+
+// settings taken from
+// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
+const uint32_t FNV_PRIME = 16777619;
+const uint32_t FNV_OFFSET_BASIS = 2166136261;
+
+uint32_t Hashmap_fnv1a_hash(void *data)
+{
+ bstring s = (bstring)data;
+ uint32_t hash = FNV_OFFSET_BASIS;
+ int i = 0;
+
+ for(i = 0; i < blength(s); i++) {
+ hash ^= bchare(s, i, 0);
+ hash *= FNV_PRIME;
+ }
+
+ return hash;
+}
+
+const int MOD_ADLER = 65521;
+
+uint32_t Hashmap_adler32_hash(void *data)
+{
+ bstring s = (bstring)data;
+ uint32_t a = 1, b = 0;
+ int i = 0;
+
+ for (i = 0; i < blength(s); i++)
+ {
+ a = (a + bchare(s, i, 0)) % MOD_ADLER;
+ b = (b + a) % MOD_ADLER;
+ }
+
+ return (b << 16) | a;
+}
+
+uint32_t Hashmap_djb_hash(void *data)
+{
+ bstring s = (bstring)data;
+ uint32_t hash = 5381;
+ int i = 0;
+
+ for(i = 0; i < blength(s); i++) {
+ hash = ((hash << 5) + hash) + bchare(s, i, 0); /* hash * 33 + c */
+ }
+
+ return hash;
+}
+
View
12 src/lcthw/hashmap_algos.h
@@ -0,0 +1,12 @@
+#ifndef hashmap_algos_h
+#define hashmap_algos_h
+
+#include <stdint.h>
+
+uint32_t Hashmap_fnv1a_hash(void *data);
+
+uint32_t Hashmap_adler32_hash(void *data);
+
+uint32_t Hashmap_djb_hash(void *data);
+
+#endif
View
118 src/lcthw/radixmap.c
@@ -8,9 +8,38 @@
#include <lcthw/radixmap.h>
#include <lcthw/dbg.h>
+RadixMap *RadixMap_create(size_t max)
+{
+ RadixMap *map = calloc(sizeof(RadixMap), 1);
+ check_mem(map);
+
+ map->contents = calloc(sizeof(RMElement), max + 1);
+ check_mem(map->contents);
+
+ map->temp = calloc(sizeof(RMElement), max + 1);
+ check_mem(map->temp);
+
+ map->max = max;
+ map->end = 0;
+
+ return map;
+error:
+ return NULL;
+}
+
+void RadixMap_destroy(RadixMap *map)
+{
+ if(map) {
+ free(map->contents);
+ free(map->temp);
+ free(map);
+ }
+}
+
+
#define ByteOf(x,y) (((uint8_t *)x)[(y)])
-static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64_t *dest)
+static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest)
{
uint64_t count[256] = {0};
uint64_t *cp = NULL;
@@ -20,7 +49,7 @@ static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64
uint64_t c = 0;
// count occurences of every byte value
- for (sp = source, end = source + N; sp < end; sp++) {
+ for (sp = source, end = source + max; sp < end; sp++) {
count[ByteOf(sp, offset)]++;
}
@@ -32,7 +61,7 @@ static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64
}
// fill dest with the right values in the right place
- for (sp = source, end = source + N; sp < end; sp++) {
+ for (sp = source, end = source + max; sp < end; sp++) {
cp = count + ByteOf(sp, offset);
dest[*cp] = *sp;
++(*cp);
@@ -50,35 +79,6 @@ void RadixMap_sort(RadixMap *map)
radix_sort(3, map->end, temp, source);
}
-/**
- * This is primarily used by the tail sorted version to find the
- * lowest place to start sorting. It's a quick binary search
- * of the data elements and returns whatever lowest value was
- * hit.
- */
-RMElement *RadixMap_find_lowest(RadixMap *map, uint32_t to_find)
-{
- int low = 0;
- int high = map->end - 1;
- RMElement *data = map->contents;
-
- while (low <= high) {
- int middle = low + (high - low)/2;
- uint32_t key = data[middle].data.key;
-
- if (to_find < key) {
- high = middle - 1;
- } else if (to_find > key) {
- low = middle + 1;
- } else {
- return &data[middle];
- }
- }
-
- return &data[low];
-}
-
-
RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
{
int low = 0;
@@ -101,36 +101,6 @@ RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
return NULL;
}
-
-RadixMap *RadixMap_create(size_t max)
-{
- RadixMap *map = calloc(sizeof(RadixMap), 1);
- check_mem(map);
-
- map->contents = calloc(sizeof(RMElement), max + 1);
- check_mem(map->contents);
-
- map->temp = calloc(sizeof(RMElement), max + 1);
- check_mem(map->temp);
-
- map->max = max;
- map->end = 0;
-
- return map;
-error:
- return NULL;
-}
-
-void RadixMap_destroy(RadixMap *map)
-{
- if(map) {
- free(map->contents);
- free(map->temp);
- free(map);
- }
-}
-
-
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value)
{
check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX.");
@@ -168,27 +138,3 @@ int RadixMap_delete(RadixMap *map, RMElement *el)
}
-uint32_t RadixMap_push(RadixMap *map, uint32_t value)
-{
- check(map->end + 1 < map->max, "RadixMap is full.");
- map->counter++;
-
- if(map->counter == UINT32_MAX) {
- // wrap it around so that we skip the ending trigger
- map->counter = 0;
- }
-
- if(map->end == 0 || map->contents[map->end-1].data.key < map->counter) {
- // this one already fits on the end so we're done
- RMElement element = {.data = {.key = map->counter, .value = value}};
- map->contents[map->end++] = element;
- } else {
- // looks like we probably wrapped around and need to do the slower add
- check(RadixMap_add(map, map->counter, value) == 0, "Failed to add on push.");
- }
-
- return map->counter;
-
-error:
- return UINT32_MAX;
-}
View
63 tests/hashmap_algos_tests.c
@@ -0,0 +1,63 @@
+#include <lcthw/bstrlib.h>
+#include <lcthw/hashmap_algos.h>
+#include "minunit.h"
+
+struct tagbstring test1 = bsStatic("test data 1");
+struct tagbstring test2 = bsStatic("test data 2");
+struct tagbstring test3 = bsStatic("xest data 3");
+
+char *test_fnv1a()
+{
+ uint32_t hash = Hashmap_fnv1a_hash(&test1);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_fnv1a_hash(&test2);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_fnv1a_hash(&test3);
+ debug("HASH: %u", hash);
+
+ return NULL;
+}
+
+char *test_adler32()
+{
+ uint32_t hash = Hashmap_adler32_hash(&test1);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_adler32_hash(&test2);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_adler32_hash(&test3);
+ debug("HASH: %u", hash);
+
+ return NULL;
+}
+
+char *test_djb()
+{
+ uint32_t hash = Hashmap_djb_hash(&test1);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_djb_hash(&test2);
+ debug("HASH: %u", hash);
+
+ hash = Hashmap_djb_hash(&test3);
+ debug("HASH: %u", hash);
+
+ return NULL;
+}
+
+char *all_tests()
+{
+ mu_suite_start();
+
+ mu_run_test(test_fnv1a);
+ mu_run_test(test_adler32);
+ mu_run_test(test_djb);
+
+ return NULL;
+}
+
+RUN_TESTS(all_tests);
+
View
86 tests/radixmap_tests.c
@@ -17,19 +17,6 @@ static int make_random(RadixMap *map)
return 0;
}
-static int push_random_values(RadixMap *map)
-{
- size_t i = 0;
- for(i = 0; i < map->max - 1; i++) {
- uint32_t value = (uint32_t)(rand () | (rand () << 16));
- uint32_t key = RadixMap_push(map, value);
- check(key != UINT32_MAX, "Got an invalid return.");
- }
- return 1;
-error:
- return 0;
-}
-
static int check_order(RadixMap *map)
{
RMElement d1, d2;
@@ -84,18 +71,6 @@ static char *test_operations()
mu_assert(test_search(map), "Failed the search test.");
mu_assert(check_order(map), "RadixMap didn't stay sorted after search.");
- RadixMap_destroy(map);
-
- map = RadixMap_create(N);
- mu_assert(map != NULL, "Failed to make the map.");
-
- debug("PUSHING VALUES");
- mu_assert(push_random_values(map), "Didn't push random values.");
- debug("VALUES PUSHED!");
-
- mu_assert(check_order(map), "Map wasn't sorted after pushes.");
-
- debug("DOING DELETES");
while(map->end > 0) {
RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key);
mu_assert(el != NULL, "Should get a result.");
@@ -115,73 +90,12 @@ static char *test_operations()
}
-static char *test_simulate()
-{
- uint32_t fd = (uint32_t)(rand() | (rand() << 16));
- int i = 0;
- size_t key = 0;
- int connects = 0, disconnects = 0, activities = 0;
- RMElement *el = NULL;
- RadixMap *map = RadixMap_create(500);
- // start the counter at just near max to test that out
- map->counter = UINT32_MAX - 100;
-
- debug("COUNTER: %u", map->counter);
-
- for(i = 0; i < 10; i++) {
- // seed it up
- RadixMap_push(map, fd++);
- }
-
- debug("ENTERING LOOP");
- for(i = 0; i < 10000; i++) {
- switch((rand() + 1) % 4) {
- case 0:
- // connect, so add it on
- RadixMap_push(map, fd++);
- connects++;
- break;
- case 1:
- // disconnect, so remove
- if(map->end > 0) {
- key = (rand() + 1) % map->end;
- el = &map->contents[key];
- el = RadixMap_find(map, el->data.key);
- mu_assert(el != NULL, "Failed to find the key.");
- RadixMap_delete(map, el);
- }
- disconnects++;
- break;
-
- default:
- // activity so find for doing stuff
- if(map->end > 0) {
- key = (rand() + 1) % map->end;
- el = &map->contents[key];
- el = RadixMap_find(map, el->data.key);
- mu_assert(el != NULL, "Failed to find the key.");
- }
- activities++;
- break;
- }
-
- if(map->end == 0) {
- // make a new connect if we're empty
- RadixMap_push(map, fd++);
- }
- }
-
- RadixMap_destroy(map);
- return NULL;
-}
-
char *all_tests()
{
mu_suite_start();
srand(time(NULL));
mu_run_test(test_operations);
- mu_run_test(test_simulate);
return NULL;
}

No commit comments for this range

Something went wrong with that request. Please try again.