C · Quickstart

Quickstart

3.0.0-rc.1 · 4c3e5023

Every verb takes one argument struct, initialized by designator, so every field left out keeps its default. Every struct opens in the same order: the handle, executor, outcome, then completion; inputs follow, then outputs and the arena they land in, then knobs, and last progress and stats. Structs carry no size or version field, so they grow source-compatibly only, and the major version changes whenever one does.

#include <stdio.h>           // For printing.
#include <usearch/usearch.h> // For the win 🚀

int main(void) {
    usearch_outcome_t outcome = {0};
    usearch_executor_t executor = NULL;
    usearch_arena_t arena = NULL;
    usearch_dense_index_t index = NULL;
    usearch_key_t keys[2] = {{.bytes[15] = 1}, {.bytes[15] = 2}};
    float vectors[2][128] = {{0}};
    usearch_matches_view_t matches = {0};

    // Threads live in the executor, the data lives in the index, and outputs land in the arena.
    usearch_executor_for_ram(&(usearch_executor_for_ram_t) {.executor = &executor, .outcome = &outcome});
    if (outcome.status != usearch_status_success_k) goto cleanup;
    usearch_arena_init(&(usearch_arena_init_t) {.arena = &arena, .executor = executor, .outcome = &outcome});
    if (outcome.status != usearch_status_success_k) goto cleanup;
    usearch_dense_init_ram(&(usearch_dense_init_ram_t) {.index = &index,
                                                        .outcome = &outcome,
                                                        .metric = usearch_dense_metric_angular_k,
                                                        .quantization = usearch_scalar_bf16_k,
                                                        .dimensions = 128});
    if (outcome.status != usearch_status_success_k) goto cleanup;

    // Populate:
    usearch_dense_insert(
        &(usearch_dense_insert_t) {.index = index,
                                   .executor = executor,
                                   .outcome = &outcome,
                                   .count = 2,
                                   .keys = {keys, sizeof(usearch_key_t)},
                                   .vectors = {vectors, sizeof(vectors[0]), 128, usearch_scalar_f32_k}});
    if (outcome.status != usearch_status_success_k) goto cleanup;

    // Search one query; a zero stride would repeat it across a larger `count`.
    usearch_dense_search(&(usearch_dense_search_t) {.index = index,
                                                    .executor = executor,
                                                    .outcome = &outcome,
                                                    .count = 1,
                                                    .queries = {vectors[0], 0, 128, usearch_scalar_f32_k},
                                                    .matches = &matches,
                                                    .arena = arena,
                                                    .wanted = 10});
    if (outcome.status != usearch_status_success_k) goto cleanup;
    printf("Found %zu matches\n", matches.counts[0]);

cleanup:
    if (outcome.message) fprintf(stderr, "%s: %s\n", usearch_status_name(outcome.status), outcome.message);
    usearch_dense_free(index);
    usearch_arena_free(arena);
    usearch_executor_free(executor);
    return outcome.status == usearch_status_success_k ? 0 : 1;
}

Every call here blocks, so its outcome is final by the time it returns.