← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
hash_table.c File Reference
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "tokenizer/hash_table.h"
#include "tokenizer/murmurhash3.h"

Go to the source code of this file.

Macros

#define CK_TOKENIZER_HASH_SEED   0x9747b28c
 

Functions

uint32_t ck_tokenizer_hash (const char *key, size_t len)
 
uint32_t ck_tokenizer_hash_str (const char *key)
 
void ck_tokenizer_hash_table_clear (CKTokenizerHashTable *table, bool free_values)
 
bool ck_tokenizer_hash_table_contains (CKTokenizerHashTable *table, const char *key)
 
size_t ck_tokenizer_hash_table_count (CKTokenizerHashTable *table)
 
CKTokenizerHashTableck_tokenizer_hash_table_create (size_t bucket_count)
 
int ck_tokenizer_hash_table_delete (CKTokenizerHashTable *table, const char *key, bool free_value)
 
void ck_tokenizer_hash_table_free (CKTokenizerHashTable *table, bool free_values)
 
int ck_tokenizer_hash_table_insert (CKTokenizerHashTable *table, const char *key, void *value)
 
int ck_tokenizer_hash_table_iterate (CKTokenizerHashTable *table, CKTokenizerHashCallback callback, void *user_data)
 
size_t ck_tokenizer_hash_table_keys (CKTokenizerHashTable *table, const char **out_keys, size_t max_keys)
 
void * ck_tokenizer_hash_table_lookup (CKTokenizerHashTable *table, const char *key)
 
void * ck_tokenizer_hash_table_lookup_avx (CKTokenizerHashTable *table, const char *key)
 
static CKTokenizerHashEntrycreate_entry (const char *key, const void *value, size_t value_size)
 
static void free_entry (CKTokenizerHashEntry *entry, bool free_value)
 
static int simd_strcmp (const char *s1, const char *s2)
 

Macro Definition Documentation

◆ CK_TOKENIZER_HASH_SEED

#define CK_TOKENIZER_HASH_SEED   0x9747b28c

Definition at line 20 of file hash_table.c.

Function Documentation

◆ ck_tokenizer_hash()

uint32_t ck_tokenizer_hash ( const char *  key,
size_t  len 
)

Definition at line 22 of file hash_table.c.

22 {
23 return ck_murmurhash3(key, (uint32_t)len, CK_TOKENIZER_HASH_SEED);
24}
#define CK_TOKENIZER_HASH_SEED
Definition hash_table.c:20
uint32_t ck_murmurhash3(const char *key, uint32_t len, uint32_t seed)
Definition murmurhash3.c:11

References ck_murmurhash3(), and CK_TOKENIZER_HASH_SEED.

◆ ck_tokenizer_hash_str()

uint32_t ck_tokenizer_hash_str ( const char *  key)

Definition at line 26 of file hash_table.c.

26 {
28}
static uint32_t ck_murmurhash3_str(const char *str, uint32_t seed)
Definition murmurhash3.h:55

References ck_murmurhash3_str(), and CK_TOKENIZER_HASH_SEED.

Referenced by ck_tokenizer_hash_table_delete(), ck_tokenizer_hash_table_insert(), ck_tokenizer_hash_table_lookup(), and ck_tokenizer_hash_table_lookup_avx().

◆ ck_tokenizer_hash_table_clear()

void ck_tokenizer_hash_table_clear ( CKTokenizerHashTable table,
bool  free_values 
)

Clear all entries (but keep bucket array).

Parameters
tableHash table
free_valuesIf true, free all value pointers

Definition at line 316 of file hash_table.c.

316 {
317 if (!table) {
318 return;
319 }
320
321 for (size_t i = 0; i < table->size; i++) {
322 CKTokenizerHashEntry *entry = table->entries[i];
323 while (entry) {
324 CKTokenizerHashEntry *next = entry->next;
325 free_entry(entry, free_values);
326 entry = next;
327 }
328 table->entries[i] = NULL;
329 }
330
331 table->count = 0;
332}
static void free_entry(CKTokenizerHashEntry *entry, bool free_value)
Definition hash_table.c:135
struct CKTokenizerHashEntry * next
Definition hash_table.h:25
CKTokenizerHashEntry ** entries
Definition hash_table.h:30

References CKTokenizerHashTable::count, CKTokenizerHashTable::entries, free_entry(), CKTokenizerHashEntry::next, and CKTokenizerHashTable::size.

Referenced by ck_tokenizer_reset().

◆ ck_tokenizer_hash_table_contains()

bool ck_tokenizer_hash_table_contains ( CKTokenizerHashTable table,
const char *  key 
)

Check if key exists.

Parameters
tableHash table
keyKey to check
Returns
true if key exists

Definition at line 272 of file hash_table.c.

272 {
273 return ck_tokenizer_hash_table_lookup(table, key) != NULL;
274}
void * ck_tokenizer_hash_table_lookup(CKTokenizerHashTable *table, const char *key)
Definition hash_table.c:202

References ck_tokenizer_hash_table_lookup().

◆ ck_tokenizer_hash_table_count()

size_t ck_tokenizer_hash_table_count ( CKTokenizerHashTable table)

Get the number of entries.

Parameters
tableHash table
Returns
Number of entries

Definition at line 268 of file hash_table.c.

268 {
269 return table ? table->count : 0;
270}

References CKTokenizerHashTable::count.

◆ ck_tokenizer_hash_table_create()

CKTokenizerHashTable * ck_tokenizer_hash_table_create ( size_t  bucket_count)

Create a hash table.

Parameters
bucket_countNumber of buckets (0 = auto-size)
Returns
Newly allocated hash table, or NULL on error

Definition at line 84 of file hash_table.c.

84 {
85 if (bucket_count == 0) {
86 bucket_count = CK_TOKENIZER_HT_BUCKETS_SMALL;
87 }
88
90 if (!table) {
91 return NULL;
92 }
93
94 table->entries = (CKTokenizerHashEntry **)calloc(bucket_count, sizeof(CKTokenizerHashEntry *));
95 if (!table->entries) {
96 free(table);
97 return NULL;
98 }
99
100 table->size = bucket_count;
101 table->count = 0;
102 table->load_factor = 0.75f;
103
104 return table;
105}
#define CK_TOKENIZER_HT_BUCKETS_SMALL
Definition hash_table.h:140

References CK_TOKENIZER_HT_BUCKETS_SMALL, CKTokenizerHashTable::count, CKTokenizerHashTable::entries, CKTokenizerHashTable::load_factor, and CKTokenizerHashTable::size.

Referenced by ck_tokenizer_create(), and ck_true_bpe_create().

◆ ck_tokenizer_hash_table_delete()

int ck_tokenizer_hash_table_delete ( CKTokenizerHashTable table,
const char *  key,
bool  free_value 
)

Delete a key.

Parameters
tableHash table
keyKey to delete
free_valueIf true, free the value pointer
Returns
0 if found and deleted, -1 if not found

Definition at line 239 of file hash_table.c.

241 {
242 if (!table || !key) {
243 return -1;
244 }
245
246 uint32_t bucket = ck_tokenizer_hash_str(key) % table->size;
247 CKTokenizerHashEntry *entry = table->entries[bucket];
248 CKTokenizerHashEntry *prev = NULL;
249
250 while (entry) {
251 if (strcmp(entry->key, key) == 0) {
252 if (prev) {
253 prev->next = entry->next;
254 } else {
255 table->entries[bucket] = entry->next;
256 }
257 free_entry(entry, free_value);
258 table->count--;
259 return 0;
260 }
261 prev = entry;
262 entry = entry->next;
263 }
264
265 return -1;
266}
uint32_t ck_tokenizer_hash_str(const char *key)
Definition hash_table.c:26

References ck_tokenizer_hash_str(), CKTokenizerHashTable::count, CKTokenizerHashTable::entries, free_entry(), CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, and CKTokenizerHashTable::size.

◆ ck_tokenizer_hash_table_free()

void ck_tokenizer_hash_table_free ( CKTokenizerHashTable table,
bool  free_values 
)

Free a hash table.

Parameters
tableHash table to free
free_valuesIf true, also free all value pointers

Definition at line 144 of file hash_table.c.

144 {
145 if (!table) {
146 return;
147 }
148
149 for (size_t i = 0; i < table->size; i++) {
150 CKTokenizerHashEntry *entry = table->entries[i];
151 while (entry) {
152 CKTokenizerHashEntry *next = entry->next;
153 free_entry(entry, free_values);
154 entry = next;
155 }
156 }
157
158 free(table->entries);
159 free(table);
160}

References CKTokenizerHashTable::entries, free_entry(), CKTokenizerHashEntry::next, and CKTokenizerHashTable::size.

Referenced by ck_tokenizer_create(), ck_tokenizer_free(), ck_true_bpe_create(), and ck_true_bpe_free().

◆ ck_tokenizer_hash_table_insert()

int ck_tokenizer_hash_table_insert ( CKTokenizerHashTable table,
const char *  key,
void *  value 
)

Insert a key-value pair.

Parameters
tableHash table
keyKey string
valueValue pointer
Returns
0 on success, -1 on error

Definition at line 162 of file hash_table.c.

164 {
165 if (!table || !key) {
166 return -1;
167 }
168
169 uint32_t bucket = ck_tokenizer_hash_str(key) % table->size;
170 CKTokenizerHashEntry *entry = table->entries[bucket];
171
172 /* Check if key already exists */
173 while (entry) {
174 if (strcmp(entry->key, key) == 0) {
175 /* Update existing entry - just replace value pointer */
176 entry->value = value;
177 return 0;
178 }
179 entry = entry->next;
180 }
181
182 /* Create new entry with NULL value (caller manages memory) */
183 CKTokenizerHashEntry *new_entry = (CKTokenizerHashEntry *)malloc(sizeof(CKTokenizerHashEntry));
184 if (!new_entry) {
185 return -1;
186 }
187
188 new_entry->key = strdup(key);
189 if (!new_entry->key) {
190 free(new_entry);
191 return -1;
192 }
193
194 new_entry->value = value;
195 new_entry->next = table->entries[bucket];
196 table->entries[bucket] = new_entry;
197 table->count++;
198
199 return 0;
200}

References ck_tokenizer_hash_str(), CKTokenizerHashTable::count, CKTokenizerHashTable::entries, CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, CKTokenizerHashTable::size, and CKTokenizerHashEntry::value.

Referenced by ck_tokenizer_add_token(), and ck_true_bpe_add_token().

◆ ck_tokenizer_hash_table_iterate()

int ck_tokenizer_hash_table_iterate ( CKTokenizerHashTable table,
CKTokenizerHashCallback  callback,
void *  user_data 
)

Definition at line 276 of file hash_table.c.

278 {
279 if (!table || !callback) {
280 return -1;
281 }
282
283 for (size_t i = 0; i < table->size; i++) {
284 CKTokenizerHashEntry *entry = table->entries[i];
285 while (entry) {
286 int ret = callback(entry->key, entry->value, user_data);
287 if (ret != 0) {
288 return ret;
289 }
290 entry = entry->next;
291 }
292 }
293
294 return 0;
295}

References CKTokenizerHashTable::entries, CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, CKTokenizerHashTable::size, and CKTokenizerHashEntry::value.

◆ ck_tokenizer_hash_table_keys()

size_t ck_tokenizer_hash_table_keys ( CKTokenizerHashTable table,
const char **  out_keys,
size_t  max_keys 
)

Get all keys as an array.

Parameters
tableHash table
out_keysOutput array for keys (must be pre-allocated)
max_keysMaximum keys to write
Returns
Number of keys written

Definition at line 297 of file hash_table.c.

299 {
300 if (!table || !out_keys) {
301 return 0;
302 }
303
304 size_t written = 0;
305 for (size_t i = 0; i < table->size && written < max_keys; i++) {
306 CKTokenizerHashEntry *entry = table->entries[i];
307 while (entry && written < max_keys) {
308 out_keys[written++] = entry->key;
309 entry = entry->next;
310 }
311 }
312
313 return written;
314}

References CKTokenizerHashTable::entries, CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, and CKTokenizerHashTable::size.

◆ ck_tokenizer_hash_table_lookup()

void * ck_tokenizer_hash_table_lookup ( CKTokenizerHashTable table,
const char *  key 
)

Look up a key.

Parameters
tableHash table
keyKey to look up
Returns
Value pointer, or NULL if not found

Definition at line 202 of file hash_table.c.

202 {
203 if (!table || !key) {
204 return NULL;
205 }
206
207 uint32_t bucket = ck_tokenizer_hash_str(key) % table->size;
208 CKTokenizerHashEntry *entry = table->entries[bucket];
209
210 while (entry) {
211 if (strcmp(entry->key, key) == 0) {
212 return entry->value;
213 }
214 entry = entry->next;
215 }
216
217 return NULL;
218}

References ck_tokenizer_hash_str(), CKTokenizerHashTable::entries, CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, CKTokenizerHashTable::size, and CKTokenizerHashEntry::value.

Referenced by ck_tokenizer_add_special_token(), ck_tokenizer_add_token(), ck_tokenizer_hash_table_contains(), ck_tokenizer_lookup(), ck_tokenizer_lookup_exact(), ck_true_bpe_add_merge_by_tokens(), ck_true_bpe_add_token(), find_longest_match_hash(), lookup_token_exact(), spm_count_unknown_run(), spm_find_candidates_at_pos(), and spm_find_special_token_at_pos().

◆ ck_tokenizer_hash_table_lookup_avx()

void * ck_tokenizer_hash_table_lookup_avx ( CKTokenizerHashTable table,
const char *  key 
)

Definition at line 221 of file hash_table.c.

221 {
222 if (!table || !key) {
223 return NULL;
224 }
225
226 uint32_t bucket = ck_tokenizer_hash_str(key) % table->size;
227 CKTokenizerHashEntry *entry = table->entries[bucket];
228
229 while (entry) {
230 if (simd_strcmp(entry->key, key) == 0) {
231 return entry->value;
232 }
233 entry = entry->next;
234 }
235
236 return NULL;
237}
static int simd_strcmp(const char *s1, const char *s2)
Definition hash_table.c:32

References ck_tokenizer_hash_str(), CKTokenizerHashTable::entries, CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, simd_strcmp(), CKTokenizerHashTable::size, and CKTokenizerHashEntry::value.

◆ create_entry()

static CKTokenizerHashEntry * create_entry ( const char *  key,
const void *  value,
size_t  value_size 
)
static

Definition at line 107 of file hash_table.c.

107 {
109 if (!entry) {
110 return NULL;
111 }
112
113 entry->key = strdup(key);
114 if (!entry->key) {
115 free(entry);
116 return NULL;
117 }
118
119 if (value) {
120 entry->value = malloc(value_size);
121 if (!entry->value) {
122 free(entry->key);
123 free(entry);
124 return NULL;
125 }
126 memcpy(entry->value, value, value_size);
127 } else {
128 entry->value = NULL;
129 }
130
131 entry->next = NULL;
132 return entry;
133}

References CKTokenizerHashEntry::key, CKTokenizerHashEntry::next, and CKTokenizerHashEntry::value.

◆ free_entry()

static void free_entry ( CKTokenizerHashEntry entry,
bool  free_value 
)
static

Definition at line 135 of file hash_table.c.

135 {
136 if (!entry) return;
137 free(entry->key);
138 if (free_value && entry->value) {
139 free(entry->value);
140 }
141 free(entry);
142}

References CKTokenizerHashEntry::key, and CKTokenizerHashEntry::value.

Referenced by ck_tokenizer_hash_table_clear(), ck_tokenizer_hash_table_delete(), and ck_tokenizer_hash_table_free().

◆ simd_strcmp()

static int simd_strcmp ( const char *  s1,
const char *  s2 
)
inlinestatic

Definition at line 32 of file hash_table.c.

32 {
33 size_t len1 = strlen(s1);
34 size_t len2 = strlen(s2);
35
36 /* Fallback to regular strcmp for short strings */
37 if (len1 < 64 || len2 < 64) {
38 return strcmp(s1, s2);
39 }
40
41#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512DQ__)
42 /* AVX-512 path */
43 while (1) {
44 /* Load 64 bytes from each string into AVX-512 registers */
45 __m512i chunk1 = _mm512_loadu_si512((const __m512i *)s1);
46 __m512i chunk2 = _mm512_loadu_si512((const __m512i *)s2);
47
48 /* Compare the chunks byte by byte */
49 __mmask64 cmp_mask = _mm512_cmpeq_epu8_mask(chunk1, chunk2);
50
51 /* Check if all bytes are equal */
52 if (cmp_mask != 0xFFFFFFFFFFFFFFFF) {
53 /* Find the first differing byte */
54 int first_diff = __builtin_ctzll(~cmp_mask);
55 return (unsigned char)s1[first_diff] - (unsigned char)s2[first_diff];
56 }
57
58 /* Check if we hit a null character in s1 or s2 */
59 __mmask64 null_mask1 = _mm512_test_epi8_mask(chunk1, _mm512_set1_epi8('\0'));
60 __mmask64 null_mask2 = _mm512_test_epi8_mask(chunk2, _mm512_set1_epi8('\0'));
61
62 if (null_mask1 || null_mask2) {
63 if (len1 == len2) {
64 return 0;
65 } else {
66 return (len1 < len2) ? -1 : 1;
67 }
68 }
69
70 /* Advance the pointers by 64 bytes for the next iteration */
71 s1 += 64;
72 s2 += 64;
73 }
74#else
75 /* SSE/AVX fallback - just use regular strcmp for simplicity */
76 (void)s1;
77 (void)s2;
78 (void)len1;
79 (void)len2;
80 return strcmp(s1, s2);
81#endif
82}

Referenced by ck_tokenizer_hash_table_lookup_avx().