Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

Hash functions #10

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
96 changes: 96 additions & 0 deletions src/hash_functions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "hash_functions.h"
#include "memory.h"

size_t hash_map_default_hash_func(const void *key, size_t capacity, int len) {
return *((size_t *) key) % capacity;
}

size_t additive(const void *key, size_t capacity, int len) {
const char *key2 = (const char *) key;
int hash = len;

for (int i = 0; i < len; ++i) {
hash += key2[i];
}


return (hash % capacity);
}

size_t pearson_hash(const void *x_copy, size_t capacity, int len) {
int h, i, j;
unsigned char ch;
size_t hex;

// to store h values
struct {
int a;
} hh[8];

// 256 values 0-255 in any (random) order suffices
struct DAT {
int a;
}

T[256] = {
98, 6, 85, 150, 36, 23, 112, 164, 135, 207, 169, 5, 26, 64, 165, 219, // 1
61, 20, 68, 89, 130, 63, 52, 102, 24, 229, 132, 245, 80, 216, 195, 115, // 2
90, 168, 156, 203, 177, 120, 2, 190, 188, 7, 100, 185, 174, 243, 162, 10, // 3
237, 18, 253, 225, 8, 208, 172, 244, 255, 126, 101, 79, 145, 235, 228, 121, // 4
123, 251, 67, 250, 161, 0, 107, 97, 241, 111, 181, 82, 249, 33, 69, 55, // 5
59, 153, 29, 9, 213, 167, 84, 93, 30, 46, 94, 75, 151, 114, 73, 222, // 6
197, 96, 210, 45, 16, 227, 248, 202, 51, 152, 252, 125, 81, 206, 215, 186, // 7
39, 158, 178, 187, 131, 136, 1, 49, 50, 17, 141, 91, 47, 129, 60, 99, // 8
154, 35, 86, 171, 105, 34, 38, 200, 147, 58, 77, 118, 173, 246, 76, 254, // 9
133, 232, 196, 144, 198, 124, 53, 4, 108, 74, 223, 234, 134, 230, 157, 139, // 10
189, 205, 199, 128, 176, 19, 211, 236, 127, 192, 231, 70, 233, 88, 146, 44, // 11
183, 201, 22, 83, 13, 214, 116, 109, 159, 32, 95, 226, 140, 220, 57, 12, // 12
221, 31, 209, 182, 143, 92, 149, 184, 148, 62, 113, 65, 37, 27, 106, 166, // 13
3, 14, 204, 72, 21, 41, 56, 66, 28, 193, 40, 217, 25, 54, 179, 117, // 14
238, 87, 240, 155, 180, 170, 242, 212, 191, 163, 78, 218, 137, 194, 175, 110, // 15
43, 119, 224, 71, 122, 142, 42, 160, 104, 48, 247, 103, 15, 11, 138, 239 // 16
};

char *x = safe_malloc(len);
memcpy(x, x_copy, len);

int r;
ch = x[0]; // save first byte
for (j = 0 ; j < 8; j++) {
// standard Pearson hash (output is h)
h = 0;

for (i = 0; i < len; i++) {
r = abs(h ^ x[i]);
h = T[r].a;
}

hh[j].a = h; // store result
x[0] = x[0] + 1; // increment first data byte by 1
}

x[0] = ch; // restore first byte

safe_free(x);

// concatenate the 8 stored values of h
/*sprintf(hex,"%02X%02X%02X%02X%02X%02X%02X%02X",
hh[0].a, hh[1].a,
hh[2].a, hh[3].a,
hh[4].a, hh[5].a,
hh[6].a, hh[7].a);*/

// For now let me do it this way, but Liu doesn't think this is a good thing
for (int i = 0; i < 8; i++) {
hex = hex << 8;
hex = hex & hh[i].a;
}

return hex; // output 64-bit 16 hex bytes hash
}
37 changes: 37 additions & 0 deletions src/hash_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @file
* Implementation of different hash functions.
*/

#ifndef HASH_FUNCTIONS_H
#define HASH_FUNCTIONS_H

/**
* The default hash function. This is the function to be used if the user does not explicitly provide any hash function. It is a basic `mod` operator.
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
size_t hash_map_default_hash_func(const void *key, size_t capacity, int len);

/**
* The additive hash function. Both the explanation and code are based on [Chasan Chouse](http://www.chasanc.com/old/hashing_func.htm)
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
size_t additive(const void *x, size_t capacity, int len);

/**
* The Pearson hash function. Both the explanation and code are based on [Wikipedia](http://en.wikipedia.org/wiki/Pearson_hashing)
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
size_t pearson_hash(const void *x, size_t capacity, int len);


#endif
21 changes: 11 additions & 10 deletions src/hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>

#include "memory.h"
#include "linked_list.h"

#include "hash_map.h"
#include "hash_functions.h"

// when "-g" is used redefine inline to static or else the linker will try to link the function and fail (since it's inline)
#ifdef TEST
Expand All @@ -17,11 +19,7 @@ inline int hash_map_default_comparator(const void *l, const void *r) {
return *((unsigned long *) l) - *((unsigned long *) r);
}

inline size_t hash_map_default_hash_func(const void *key, size_t capacity) {
return *((size_t *) key) % capacity;
}

void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func) {
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func, hash_map_key_size key_size) {
map->capacity = capacity;
map->size = 0;

Expand All @@ -40,6 +38,8 @@ void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparato
map->hash_func = hash_map_default_hash_func;
}

map->key_size = key_size;

map->keys = (linked_list *) safe_malloc(sizeof(linked_list));
// No free_data func here because keys will be free'd by linked_list_free for **table
linked_list_init(map->keys, NULL);
Expand All @@ -60,7 +60,7 @@ void hash_map_free(hash_map *map) {
}

void *hash_map_get(hash_map *map, void *key) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
return NULL;
Expand All @@ -82,12 +82,13 @@ void *hash_map_get(hash_map *map, void *key) {
}

void hash_map_put(hash_map *map, void *key, void *value) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
list = (linked_list *) safe_malloc(sizeof(linked_list));

linked_list_init(list, (linked_list_destructor) safe_free);
map->table[map->hash_func(key, map->capacity)] = list;
map->table[map->hash_func(key, map->capacity, map->key_size(key))] = list;
}

linked_list_node *head = linked_list_head(list);
Expand Down Expand Up @@ -118,7 +119,7 @@ void hash_map_put(hash_map *map, void *key, void *value) {
}

void hash_map_remove(hash_map *map, void *key) {
size_t offset = map->hash_func(key, map->capacity);
size_t offset = map->hash_func(key, map->capacity, map->key_size(key));
linked_list *list = map->table[offset];

if (!list) {
Expand Down Expand Up @@ -175,7 +176,7 @@ void hash_map_clear(hash_map *map) {
}

bool hash_map_contains_key(hash_map *map, void *key) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
return false;
Expand Down
13 changes: 11 additions & 2 deletions src/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ typedef int (*hash_map_comparator)(const void *l, const void *r);
* Hash function
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
typedef size_t (*hash_map_hash_func)(const void *key, size_t capacity);
typedef size_t (*hash_map_hash_func)(const void *key, size_t capacity, int len);

/**
* Size function to determine the size of each keys in the hash function
* @return the size of each key`
*/
typedef size_t (*hash_map_key_size)();

/**
* Hash map object
Expand All @@ -40,6 +47,8 @@ typedef struct {
hash_map_comparator comparator;
/** Key hash function */
hash_map_hash_func hash_func;
/** Key size function */
hash_map_key_size key_size;
/** Keys */
linked_list *keys;
} hash_map;
Expand All @@ -61,7 +70,7 @@ typedef struct {
* @param comparator key comparator function
* @param hash_func key hash function
*/
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func);
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func, hash_map_key_size);

/**
* Free the hash map.
Expand Down
1 change: 0 additions & 1 deletion src/memory.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "memory.h"

#include <stdio.h>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try not to include changes like this. I usually look at the diff before committing to make sure I don't have stuff like this.

#include <stdlib.h>

Expand Down
Loading