Created
May 11, 2022 16:12
-
-
Save worldOneo/69f6b2c8330b1b9838750bd92c2f1bb7 to your computer and use it in GitHub Desktop.
Simple (hash) table written in C ~10ns lookups
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
typedef uint64_t u64; | |
typedef struct Table | |
{ | |
u64 nullValue; | |
bool hasNull; | |
u64 buckets; | |
u64 *map; | |
} Table; | |
static const u64 bucketSize = 8; | |
Table *alloc_table() | |
{ | |
Table *table = calloc(1, sizeof(Table)); | |
table->buckets = 8; | |
table->map = calloc(8, sizeof(u64) * bucketSize); | |
return table; | |
} | |
static inline u64 table_index(u64 bucket, u64 bucketIndex) { | |
return bucket * bucketSize + bucketIndex; | |
} | |
u64 table_get(Table *table, u64 key) | |
{ | |
if (key == 0) | |
{ | |
if (table->hasNull) | |
return table->nullValue; | |
return 0; | |
} | |
u64 bucket = key % table->buckets; | |
for (u64 i = 0; i < 8; i += 2) | |
{ | |
u64 idx = table_index(bucket, i); | |
if (table->map[idx] == key) | |
{ | |
return table->map[idx + 1]; | |
} | |
} | |
return 0; | |
} | |
void table_set(Table *table, u64 key, u64 value) | |
{ | |
if (key == 0) | |
{ | |
table->hasNull = true; | |
table->nullValue = value; | |
return; | |
} | |
u64 bucket = key % table->buckets; | |
for (u64 bucketIndex = 0; bucketIndex < 8; bucketIndex += 2) | |
{ | |
u64 idx = table_index(bucket, bucketIndex); | |
u64 mapKey = table->map[idx]; | |
if (mapKey == 0 || mapKey == key) | |
{ | |
table->map[idx] = key; | |
table->map[idx + 1] = value; | |
return; | |
} | |
} | |
// Resize map | |
u64 newBuckets = table->buckets * 2; | |
u64 *newMap = calloc(newBuckets, sizeof(u64) * bucketSize); | |
Table newTable; | |
newTable.buckets = newBuckets; | |
newTable.map = newMap; | |
for (u64 bucket = 0; bucket < table->buckets; bucket++) | |
{ | |
for (u64 bucketIndex = 0; bucketIndex < bucketSize; bucketIndex += 2) | |
{ | |
u64 idx = table_index(bucket, bucketIndex); | |
u64 mapKey = table->map[idx]; | |
if (mapKey != 0) | |
{ | |
table_set(&newTable, mapKey, table->map[idx + 1]); | |
} | |
} | |
} | |
free(table->map); | |
table->map = newMap; | |
table->buckets = newBuckets; | |
table_set(table, key, value); | |
return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment