| 371 | } |
| 372 | |
| 373 | void cbm_lsh_insert(cbm_lsh_index_t *idx, const cbm_lsh_entry_t *entry) { |
| 374 | if (!idx || !entry || !entry->fingerprint) { |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | /* Store a copy of the entry */ |
| 379 | if (idx->entry_count >= idx->entry_cap) { |
| 380 | int new_cap = |
| 381 | idx->entry_cap < ENTRY_INIT_CAP ? ENTRY_INIT_CAP : idx->entry_cap * GROW_FACTOR; |
| 382 | cbm_lsh_entry_t *new_entries = |
| 383 | realloc(idx->entries, (size_t)new_cap * sizeof(cbm_lsh_entry_t)); |
| 384 | if (!new_entries) { |
| 385 | return; |
| 386 | } |
| 387 | idx->entries = new_entries; |
| 388 | idx->entry_cap = new_cap; |
| 389 | } |
| 390 | int entry_idx = idx->entry_count; |
| 391 | idx->entries[entry_idx] = *entry; |
| 392 | idx->entry_count++; |
| 393 | |
| 394 | /* Insert index into each band's bucket */ |
| 395 | for (int b = 0; b < CBM_LSH_BANDS; b++) { |
| 396 | uint32_t h = band_hash(entry->fingerprint, b); |
| 397 | bucket_push(&idx->bands[b][h], entry_idx); |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | /* O(1) seen-set: open-addressing hash table on node_id for dedup. */ |
| 402 | typedef struct { |
no test coverage detected