typedef uint8_t usearch_byte_t; § Arenas
Every output whose length scales with the call lands in an arena: the matches of a search, every vector stored under one key, every pair a sparse product scored, a monolith, a cursor’s batch.
An arena is memory the library allocates and the caller passes to call after call, each of which rewinds it and writes views into it, growing only when the new outputs outsize everything it held.
An executor makes it where it computes, and a NULL executor makes host pages for calls on the calling thread; an arena of host pages may outlive the executor that made it.
Nothing is allocated until a call writes into it, and it keeps its high-water mark, so a steady loop allocates once.
Only fixed-size reports, such as stats, descriptions and written counts, stay fields the caller points at.
Arenas keep the interface at one verb per operation, never a twin per output style.
usearch_arena_t arena = NULL;
usearch_arena_init(&(usearch_arena_init_t) {.arena = &arena, .executor = executor, .outcome = &outcome});
for (size_t i = 0; i != 2; ++i) {
usearch_rows_view_t rows = {0};
size_t rows_count = 0;
usearch_dense_get(&(usearch_dense_get_t) {.index = index,
.executor = executor,
.outcome = &outcome,
.key = keys[i],
.vectors = &rows,
.written = &rows_count,
.arena = arena,
.outputs_scalar = usearch_scalar_f32_k});
if (outcome.status != usearch_status_success_k) break;
// `rows.data` holds `rows_count` vectors `rows.stride` bytes apart,
// valid until the next call given `arena`
}
usearch_arena_free(arena);Any verb may reuse any arena of its residency, so a search and a get can share one, as long as the first call’s views are not read after the second starts.
To keep one call’s outputs alive past the next, pass the next call another arena.
An arena serves one call at a time: a call holds it until just before its final status, and a second call naming it meanwhile finishes usearch_status_contended_k.
A NULL arena, or inputs pointing into the arena a call is about to rewind, refuse with usearch_status_invalid_argument_k, and a call that fails leaves its outputs NULL.
A GPU arena grows, fills and frees on the first stream of the executor that made it, so it serves only calls on that executor, and any other executor, NULL included, is refused with usearch_status_device_k.
Free a GPU arena before the executor that made it.
§ Rows & Scalars
A batch of rows is a usearch_rows_view_t: a base pointer, a byte stride, the values per row, and the scalar kind they hold, converted on the way in where it differs from storage.
A zero stride repeats the first row, as in BLAS, and the call’s count alone is the batch axis.
Vectors are quantized on insertion into the index’s quantization, from f64 down to i8, u8, the four 8- and 6-bit floats e5m2, e4m3, e3m2 and e2m3, and packed 4- and 1-bit integers.
The library compiles the first USEARCH_DENSE_DTYPES storage types of bf16, u1x8, i8, e4m3, f16, u8, e5m2, i4x2, u4x2, e3m2 and e2m3, and refuses the rest with usearch_status_unsupported_k.
The precompiled binaries carry all eleven, while a CMake build takes the first four unless configured with -D USEARCH_DENSE_DTYPES=11.
USearch comes pre-packaged with NumKong, bringing SIMD-accelerated distance kernels for x86, Arm, RISC-V and GPUs. The dense metric kinds are:
usearch_dense_metric_inner_k- Inner Product distance, , unnormalized and scale-sensitive.usearch_dense_metric_angular_k- Cosine distance, , in and blind to magnitude.usearch_dense_metric_euclidean_k- Euclidean distance, , zero only for identical vectors.usearch_dense_metric_hamming_k- Hamming distance, , overusearch_scalar_u1x8_kbit sets.usearch_dense_metric_jaccard_k- Jaccard distance, , in , overusearch_scalar_u1x8_kbit sets.
usearch_scalar_name, usearch_dense_metric_name and their _from_name inverses spell these sets the way every binding parses them.
§ Search
A search writes a usearch_matches_view_t into its arena: columns packed columns for each of its count queries, query i holding counts[i] matches from keys[i * columns] and scores[i * columns] on, nearest first. wanted bounds the columns, the “k” in “kANN”.
The graph’s connectivity is frozen when the index is created, while the expansion_factor, the breadth of the candidates a walk explores, is chosen per call.
Higher expansion values buy recall at the cost of latency; zero derives a default from the connectivity.
usearch_traversal_stats_t stats = {0};
usearch_dense_search(&(usearch_dense_search_t) {.index = index,
.executor = executor,
.outcome = &outcome,
.count = 1,
.queries = {query, 0, 128, usearch_scalar_f32_k},
.matches = &matches,
.arena = arena,
.wanted = 10,
.expansion_factor = 128,
.stats = &stats});.traversal = usearch_traversal_scan_k scores every published entry instead of walking, the exact ground truth a walk approximates, on RAM, NVMe and NVIDIA VRAM.
AMD and Apple VRAM handles refuse scans with usearch_status_unsupported_k.
Every verb that walks the graph fills the optional stats with the members it visited, the distances it computed, and its restarts, a connectivity health signal rather than a cost.
API
Types
usearch_byte_tOne byte of raw storage, read or written without interpretation: a key's identity, a borrowed run's contents, the buffers callers hand in.
usearch_scalar_tScalar types the indexes store and exchange, named by width and encoding.
enum usearch_scalar_t Sub-byte types pack several dimensions per byte, as their xN suffixes spell.
Values
usearch_scalar_unknown_k | 0 | No scalar named - an unset field, or a custom metric owning its own storage. |
|---|---|---|
usearch_scalar_f64_k | 1 | IEEE-754 binary64: ±1.80e308, epsilon 2.22e-16, subnormals to 4.94e-324, with infinities and NaNs. |
usearch_scalar_f32_k | 2 | IEEE-754 binary32: ±3.40e38, epsilon 1.19e-7, subnormals to 1.40e-45, with infinities and NaNs. |
usearch_scalar_bf16_k | 3 | Truncated f32 - 8-bit exponent, 7-bit mantissa: f32's range at ±3.39e38 and epsilon 7.81e-3, with infinities and NaNs. |
usearch_scalar_f16_k | 4 | IEEE-754 binary16: ±65504, epsilon 9.77e-4, subnormals to 5.96e-8, with infinities and NaNs. |
usearch_scalar_e5m2_k | 5 | FP8 with a 5-bit exponent: ±57344, epsilon 0.25, with infinities and NaNs - f16's dynamic range carried on two mantissa bits. |
usearch_scalar_e4m3_k | 6 | FP8 with a 4-bit exponent: ±448, epsilon 0.125, no infinities, and two NaN codes at 0x7F and 0xFF. |
usearch_scalar_e3m2_k | 7 | FP6 with a 3-bit exponent, byte-aligned with two padding bits: ±28, no infinities or NaNs, so every one of its 64 codes is a number. |
usearch_scalar_e2m3_k | 8 | FP6 with a 2-bit exponent, byte-aligned with two padding bits: ±7.5, no infinities or NaNs, and 72% of its codes outside [-1, 1]. |
usearch_scalar_i8_k | 10 | 8-bit signed integer spanning -128 to 127, every code a number. |
usearch_scalar_i4x2_k | 11 | Two signed nibbles per byte spanning -8 to 7, even dimensions in the low nibble and odd ones in the high. |
usearch_scalar_i32_k | 12 | 32-bit signed integer spanning ±2.15e9, every code a number. |
usearch_scalar_u8_k | 20 | 8-bit unsigned integer spanning 0 to 255, every code a number. |
usearch_scalar_u4x2_k | 21 | Two unsigned nibbles per byte spanning 0 to 15, even dimensions in the low nibble and odd ones in the high. |
usearch_scalar_u1x8_k | 22 | Eight single-bit dimensions per byte - the form the Hamming & Jaccard metrics score, where only the set-bit count of a XOR or AND carries meaning. |
Spellings
char const * usearch_scalar_name(usearch_scalar_t scalar);usearch_scalar_t usearch_scalar_from_name(usearch_bytes_view_t name);usearch_rows_view_tA run of rows along a call's batch axis - the currency of every verb whose rows share one width, borrowed from the caller as an input and written packed into an arena as an output.
struct usearch_rows_view_t An input's row count is the call's count, and the call checks columns against the frozen geometry. A zero stride repeats the first row. An output's rows are packed: the call writes one row's bytes as stride, and columns and scalar as it wrote them, so neither a repeat nor a geometry check applies.
Fields
data | void const * | Base pointer of the first row. |
|---|---|---|
stride | size_t | Bytes between the starts of consecutive rows; zero repeats the first row. |
columns | size_t | Values per row; an input's must match the frozen geometry, and sub-byte rows of either kind must fill whole bytes, or they are refused. |
scalar | usearch_scalar_t | The scalar type the rows hold, converted on the way in where it differs. |
usearch_matrix_view_tA borrowed strided matrix off the batch axis - an operand whose rows and columns are its own, like the value rows attention gathers from.
struct usearch_matrix_view_t rows and columns are counts and stride alone is in bytes. A zero stride repeats the first row.
Fields
data | void const * | Base pointer of the first row. |
|---|---|---|
rows | size_t | Rows the matrix carries. |
columns | size_t | Logical scalars per row, as the caller counts them. |
stride | size_t | Bytes between the starts of consecutive rows; zero repeats the first row. |
scalar | usearch_scalar_t | The scalar type the rows hold. |
usearch_tape_layout_tHow wide a tape's offsets are, naming the member of its offsets union to read.
enum usearch_tape_layout_t Values
usearch_tape_u32_k | 0 | Apache Arrow Binary or List, with 32-bit offsets. |
|---|---|---|
usearch_tape_u64_k | 1 | Apache Arrow LargeBinary or LargeList, the same with 64-bit offsets. |
usearch_tape_view_tA ragged batch as Apache Arrow lays one out: elements end to end, and one more offset than entries around them, borrowed as an input or written into an arena as an output.
struct usearch_tape_view_t Entry i spans elements offsets[i] up to offsets[i+1], so the last offset closes the final entry. What an element is belongs to the modality: a byte of a sequence, a point of a shape or of a geospatial set. As an output the call writes 32-bit offsets while its elements fit them, and 64-bit beyond.
Fields
data | void const * | First element of the tape, which every offset counts from. |
|---|---|---|
layout | usearch_tape_layout_t | Which member of offsets the tape spells them in. |
offsets | union usearch_tape_view_t::@255032373266025347346062347373025110336350121000 | |
scalar | usearch_scalar_t | The scalar type the elements hold: u8 for sequences, f64 degrees for geospatial inputs, and any kind for shape points, converted on the way in where it differs from storage. |
usearch_matches_view_tA ranked run a call wrote into its arena - count rows of columns packed columns, where count is the call's own.
struct usearch_matches_view_t Carries no query count of its own: the call already fixed it, and a second copy is a second thing to disagree. Query i holds counts[i] matches from keys[i · columns] and scores[i · columns] on, and the columns past them are unwritten.
What scores hold is each verb's own: a search writes distances nearest-first, whichever kind the index froze - the inner kind as 1 - dot - while the linear-algebra verbs write similarities, as their own docs state.
Fields
keys | usearch_key_t const * | First row of the keys, columns per row. |
|---|---|---|
scores | usearch_distance_t const * | First row of the scores, positionally paired with keys. |
counts | size_t const * | Matches written per query, one entry per query. |
columns | size_t | Columns per row the call wrote, at most its wanted - the "k" in "kANN". |
usearch_matches_tape_view_tA ragged run of matches a call wrote into its arena, for verbs whose queries hold as many matches as their walks found: keys and scores end to end, and one more offset than queries.
struct usearch_matches_tape_view_t Query i spans offsets[i] up to offsets[i+1] in both arrays, so the last offset is the total. Scores follow the same per-verb meaning as in usearch_matches_view_t.
Fields
keys | usearch_key_t const * | Every query's keys, end to end. |
|---|---|---|
scores | usearch_distance_t const * | Every query's scores, positionally paired with keys. |
offsets | size_t const * | The call's count + 1 non-decreasing offsets into keys and scores. |
usearch_traversal_tHow a search reaches the indexed entries it scores.
enum usearch_traversal_t Values
usearch_traversal_unknown_k | 0 | No traversal named, which derives the walk. |
|---|---|---|
usearch_traversal_walk_k | 1 | Walk the graph, scoring the entries the expansion reaches - approximate, the default. |
usearch_traversal_scan_k | 2 | Score every entry published when the query's scan starts - exact, the ground truth a walk approximates. |
Spellings
char const * usearch_traversal_name(usearch_traversal_t traversal);usearch_traversal_t usearch_traversal_from_name(
usearch_bytes_view_t name);usearch_traversal_stats_tTraversal telemetry, shared by every verb that walks a graph in every modality - a pure output, fully overwritten by the call it is passed to.
struct usearch_traversal_stats_t Passing NULL skips reporting.
Fields
visited_members | size_t | Graph members visited while resolving the batch. |
|---|---|---|
computed_distances | size_t | Distances computed while resolving the batch, diversity re-selections included. |
restarts | size_t | Starvation restarts - re-seedings after the frontier drained prematurely, and a graph-connectivity health signal rather than a cost counter. |
missing_hints | size_t | Hint keys no shard held an entry under; zero unless a search was handed hints. |
usearch_arena_tMemory the library writes every output whose length scales with a call into, reused across calls.
typedef struct usearch_arena_handle_t * usearch_arena_t; Memory
Made by usearch_arena_init where its executor computes: host pages on its memory domains, or the memory of its GPU, and a GPU that runs out reports usearch_status_out_of_memory_k rather than falling back to the host. Each call given the arena rewinds it, which invalidates every output of the previous call, and refills it, growing only when the new outputs outsize everything it held, so a steady loop allocates once. To keep one call's outputs alive past the next call, pass the next call another arena.
- A
NULLarena is refused withusearch_status_invalid_argument_k. - A call whose inputs point into the arena it is about to rewind reports
usearch_status_invalid_argument_k. - An arena serves one call at a time; a second call naming it finishes
usearch_status_contended_k, and a deferred one does so at submission. - A call on another residency or device than the arena's, or a call naming a GPU arena with another executor than the one that made it,
NULLincluded, reportsusearch_status_device_k. - A blocking call borrows the arena until it returns, and a deferred one holds it until final.
- A call that fails, is cancelled, or has nothing to report leaves its outputs
NULL.
Notes
A GPU arena grows, fills and frees on the first stream of the executor that made it, so it serves only calls on that executor, and must be freed before that executor is.
Functions
usearch_keys_view_from_arrowViews the 16-byte keys of one Arrow fixed_size_binary(16) column in place, tagged arrow.uuid or not.
usearch_status_t usearch_keys_view_from_arrow(
struct ArrowSchema const *schema,
struct ArrowArray const *array,
usearch_keys_view_t *keys,
size_t *count); A null_count of -1 with a validity buffer may hold a null, and is refused as one.
Parameters
schema | in | The column's schema. |
|---|---|---|
array | in | The column, whose offset is applied; only its lengths and pointers are read, never its buffers, so the array of an ArrowDeviceArray converts as well. |
keys | out | The keys, one every 16 bytes. |
count | out | The number of keys. |
Returns
usearch_status_invalid_argument_k for a missing or released input or one holding a null, usearch_status_unsupported_layout_k for another format, a dictionary or a view, usearch_status_malformed_k for a negative length or offset or a missing buffer, and usearch_status_overflow_k for a length past what size_t counts.
usearch_rows_view_from_arrowViews the rows of one Arrow fixed_size_list column, or of a fixed_size_binary one tagged numkong.u1x8, in place, the offsets of the column and its child applied.
usearch_status_t usearch_rows_view_from_arrow(
struct ArrowSchema const *schema,
struct ArrowArray const *array,
usearch_rows_view_t *rows,
size_t *count); Parameters
schema | in | The column's schema. |
|---|---|---|
array | in | The column, whose offset is applied. |
rows | out | The rows, packed, with their columns and scalar. |
count | out | The number of rows. |
Returns
The statuses of usearch_keys_view_from_arrow, with a list of bool refused as an unsupported layout.
usearch_tape_view_from_arrowViews one Arrow column of sequences or shapes in place: binary, utf8 or a list of 3-element lists as a tape of 32-bit offsets, and large_binary, large_utf8 or a large_list of them as one of 64-bit offsets, starting at the column's offset.
usearch_status_t usearch_tape_view_from_arrow(
struct ArrowSchema const *schema,
struct ArrowArray const *array,
usearch_tape_view_t *tape,
size_t *count); Parameters
schema | in | The column's schema. |
|---|---|---|
array | in | The column, whose offset is applied. |
tape | out | The tape, its scalar u8 for bytes and the points' otherwise. |
count | out | The number of entries. |
Returns
The statuses of usearch_keys_view_from_arrow.
usearch_keys_view_to_arrowExports count keys a call wrote into arena as one Arrow fixed_size_binary(16) column tagged as arrow.uuid, in place.
usearch_status_t usearch_keys_view_to_arrow(
usearch_keys_view_t keys,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); The array pins arena until its release: meanwhile a call naming the arena is refused with usearch_status_contended_k, and usearch_arena_free leaves the arena to the last release. Arenas on host pages export as ARROW_DEVICE_CPU, and those of a VRAM executor as ARROW_DEVICE_CUDA, ARROW_DEVICE_ROCM or ARROW_DEVICE_METAL with the vendor's ordinal of their device and no sync_event, as the call that filled one drained its uploads. The schema's name is empty, for the caller to point at its own. Schema and array release apart, and a consumer may move their children out before either release.
Statuses
usearch_status_invalid_argument_kAn output is missing, or the keys lie outsidearena.usearch_status_unsupported_layout_kThe keys are not packed.usearch_status_contended_kA call fillsarena, or another export carves it.usearch_status_out_of_memory_kAn allocation failed.
Notes
A device arena's last release must come before the free of the executor that made it, which usearch_arena_t asks of the free it stands in for.
usearch_rows_view_to_arrowExports count packed rows a call wrote into arena as one Arrow fixed_size_list column of their scalar, or a fixed_size_binary one for u1x8, in place.
usearch_status_t usearch_rows_view_to_arrow(
usearch_rows_view_t rows,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); Returns
The statuses of usearch_keys_view_to_arrow, with a scalar Arrow carries no layout for, or columns filling no whole element, refused as an unsupported layout.
usearch_tape_view_to_arrowExports a tape of count entries a call wrote into arena as one Arrow column in place, its offsets as they are: binary or large_binary for u8 elements, which a sequence's are, and a list or large_list of 3-element lists for any other scalar.
usearch_status_t usearch_tape_view_to_arrow(
usearch_tape_view_t tape,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); A list length comes from the tape's last offset, which crosses from a device arena through its driver. Shape points asked for in u8 read as binary, whose offsets are bytes, so ask a shapes get for another scalar before exporting it.
Returns
The statuses of usearch_keys_view_to_arrow, with an unknown layout refused as an unsupported one, and usearch_status_device_k for a device's last offset no driver reads.
usearch_keys_tape_view_to_arrowExports a ragged run of count entries' keys a call wrote into arena as one Arrow large_list of arrow.uuid keys, in place.
usearch_status_t usearch_keys_tape_view_to_arrow(
usearch_keys_tape_view_t keys,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); Returns
The statuses of usearch_tape_view_to_arrow.
usearch_matches_view_to_arrowExports the padded matches of count queries a call wrote into arena as one Arrow large_list_view of struct{key, distance} over their columns.
usearch_status_t usearch_matches_view_to_arrow(
usearch_matches_view_t matches,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); Keys, scores and sizes stay in place. The view's offsets are written behind the call's outputs in arena under the arena's hold, so no other call or carving export runs on arena meanwhile, and a device arena's reach its device on the first stream of the executor that made the arena.
Returns
The statuses of usearch_keys_view_to_arrow.
usearch_matches_tape_view_to_arrowExports a ragged run of count queries' matches a call wrote into arena as one Arrow large_list of struct{key, distance}, in place.
usearch_status_t usearch_matches_tape_view_to_arrow(
usearch_matches_tape_view_t matches,
size_t count,
usearch_arena_t arena,
struct ArrowSchema *schema,
struct ArrowDeviceArray *array); Returns
The statuses of usearch_tape_view_to_arrow.
usearch_dense_insertAdds a run of vectors under their keys - the native batch operation; a single vector is a count of one.
void usearch_dense_insert(usearch_dense_insert_t *arguments); Overlaps safely with concurrent searches on the same handle. Concurrency & Thread Safety
An insertion is all-or-nothing per call, with or without a handler, and its entries become visible at once on RAM and VRAM handles alike, so a concurrent search sees every entry of the call or none of them. Every entry is claimed before the handler's first report, and a claimed entry cannot be withdrawn, so the handler reports progress but cannot cancel: a returned usearch_cancel_k is ignored.
On a RAM handle every fallible step runs before the first entry identity is claimed, so a failed call leaves the index untouched. A VRAM call that fails after its first launch publishes none of its entries and leaves the handle refusing every later mutation with that failure, while searches continue.
usearch_outcome_t outcome = {0};
usearch_dense_insert(&(usearch_dense_insert_t){
.index = index, .executor = executor, .outcome = &outcome,
.count = 256, .keys = {keys, sizeof(usearch_key_t)},
.vectors = {rows_base, 128 * sizeof(float), 128, usearch_scalar_f32_k}});
if (outcome.status != usearch_status_success_k) report(outcome.message);Parameters
indexusearch_dense_index_t | The handle to be populated. | |
|---|---|---|
executorusearch_executor_t | The executor driving the batch; its kind must match the handle's residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Entries to admit - the batch axis of keys and vectors. | |
keysusearch_keys_view_t | The identities to admit the entries under, one per entry. | |
vectorsusearch_rows_view_t | The vectors to admit, converted on ingest to the stored type. | |
expansion_factorsize_t | The optional breadth of the candidates the build walk explores; zero derives. | |
progressusearch_progress_t | The optional handler, called with entries admitted, which reports and cannot cancel. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_read_only_kThe handle is a view.usearch_status_contended_kA refinement, absorption or clear holds the handle, or on VRAM a save or another insertion does; nothing is inserted.
usearch_dense_searchPerforms k-Nearest Neighbors Search for a run of queries, approximate by walking the graph or exact by scanning every entry - the native batch operation, parallelized internally.
void usearch_dense_search(usearch_dense_search_t *arguments); One query is a count of one. Never writes to the index, so any number may overlap with insertions. Concurrency & Thread Safety
A scan walks no graph. On RAM the queries split into blocks, each taken by one of the executor's threads: a block of many queries packs once into the operand layout of the CPU's matrix kernels and streams every stored vector against the pack where it lies, while a lone query takes the walk's own 4-way kernels. On NVMe the queries pack once and the threads split the value column instead, each run written beside its keys, so the column is read once and in order. Either way each query's matches merge into its output row as the pass advances. On NVIDIA VRAM the batch scans every shard's vectors on the device, where the shards' matches merge too. Every residency ranks by the distances its walk reports. A predicate is asked only about entries closer than the worst match the query already holds, which makes the scan the fallback for predicates too selective for a walk to cross.
A predicate narrows the matches to the entries it admits. Non-matching entries still route the traversal rather than terminating it, so recall does not collapse at low selectivity - the walk crosses rejected regions to reach admitted ones behind them. The cost is that the predicate judges far more keys than wanted, every scored candidate, asked about a quad of them at a time, so it belongs on the caller's fast path - and it is invoked concurrently from the executor's threads, so it must tolerate that.
hints hand each query's walk landmarks the caller already trusts, such as the matches of the same queries over another index of the same keys. A query takes as many keys as a walk draws landmarks, the connectivity rounded up to a multiple of four, and ignores the rest; the entries stored under them take the landmark slots ahead of the random draws, in hint order, as many as fit. They are advisory, so a key no entry holds is skipped and counted in missing_hints. An NVMe view resolves them through its key table, confirming each entry with one key read.
A cancelled search reports usearch_status_cancelled_k and leaves matches NULL, since a query resolved before the stop is indistinguishable from one that never ran. A zero wanted, or an index holding no entries, succeeds without walking and writes only the counts, every one zero.
static void admits_tenant(usearch_key_t const* keys, usearch_admission_t* admissions, size_t count, void* state) {
for (size_t i = 0; i != count; ++i)
admissions[i] = keys[i].bytes[0] == *(uint8_t const*)state ? usearch_admit_k : usearch_reject_k;
}
uint8_t tenant = 7;
usearch_matches_view_t matches;
usearch_outcome_t outcome = {0};
usearch_dense_search(&(usearch_dense_search_t){
.index = index, .executor = executor, .outcome = &outcome,
.count = 32, .queries = {rows_base, 256 * sizeof(float), 256, usearch_scalar_f32_k},
.matches = &matches, .arena = arena, .wanted = 10,
.predicate = {admits_tenant, &tenant}});
// Query 3's nearest key, valid until the next call given arena.
usearch_key_t nearest = matches.keys[3 * matches.columns];Parameters
indexusearch_dense_index_t | The handle to be queried. | |
|---|---|---|
executorusearch_executor_t | The executor driving the batch; its kind must match the handle's residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Queries to resolve; the outputs have count rows of wanted entries. | |
queriesusearch_rows_view_t | The query vectors to resolve, one per query. | |
matchesusearch_matches_view_t * | Output for the run, inside arena. | |
arenausearch_arena_t | Memory for matches, rewound by the call. | |
wantedsize_t | Columns per row, and the upper bound on matches - the "k" in "kANN". | |
expansion_factorsize_t | The optional breadth of the candidates a walk explores; zero derives, a scan ignores it. | |
traversalusearch_traversal_t | How entries are reached: a walk, the default, or an exact scan of every entry, on all but AMD and Apple VRAM. | |
predicateusearch_predicate_t | The optional predicate, asked about a scored quad of candidates at a time. | |
hintsusearch_matches_view_t const * | The optional keys each query's walk starts from ahead of its random landmarks, one row of counts[query] keys per query, as a search writes its matches, at most one per landmark; scores are not read, a scan ignores them, and keys no entry holds are skipped and counted in the stats. | |
progressusearch_progress_t | The optional handler, called with queries resolved. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_unknown_kind_kAtraversalother than a walk or a scan.usearch_status_unsupported_kA scan of an AMD or Apple VRAM handle, apredicateorhintson any VRAM handle, orhintson an NVMe view holding no key table.usearch_status_invalid_argument_khintsnaming no counts, or columns but no keys.usearch_status_shape_mismatch_kA hinted query counts more keys than the hints' columns.
usearch_geospatial_insertAdds observations under their keys - the native batch operation; a single observation is a batch of one.
void usearch_geospatial_insert(usearch_geospatial_insert_t *arguments); An observation without an altitude is placed on the handle's terrain when it has one, and on the ellipsoid otherwise.
An insertion is all-or-nothing per call. Every fallible step runs before the first entry identity is claimed, so a rejected call publishes nothing - a cancelled one included, which reports usearch_status_cancelled_k - and on a RAM handle the entries of an accepted one become visible at once, their keys right after.
A key already holding values_per_key entries rejects the whole call, since a smaller retry cannot help.
Parameters
indexusearch_geospatial_index_t | The handle to be populated. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Observations to admit - the batch axis of keys and observations. | |
keysusearch_keys_view_t | The identities to admit the observations under, one per entry and not necessarily unique. | |
observationsusearch_geospatial_observation_t const * | The observations, count of them. | |
expansion_factorsize_t | The optional breadth of the candidates the build walk explores - the ef of the literature; zero derives. | |
progressusearch_progress_t | The optional handler, called with entries admitted and the batch length. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_read_only_kThe handle is a view.usearch_status_invalid_argument_kAn observation lacks a latitude or a longitude, or ends before it begins.
usearch_geospatial_searchFinds the nearest entries of each query observation that the relation admits, approximate by walking the graph or exact by scanning every entry - the native batch operation, parallelized internally; one query is a batch of one.
void usearch_geospatial_search(usearch_geospatial_search_t *arguments); Scores are chord metres between the two positions, altitude included. The relation, the time window and the predicate narrow the walk's candidates, so a selective one wants a wider expansion_factor, and a query may hold fewer than wanted matches.
A predicate narrows the matches to the entries it admits. Non-matching entries still route the traversal, so recall does not collapse at low selectivity.
A cancelled search reports usearch_status_cancelled_k and leaves matches NULL.
Parameters
indexusearch_geospatial_index_t | The handle to be queried. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Queries to resolve; the outputs have count rows of wanted entries. | |
queriesusearch_geospatial_observation_t const * | The count query observations. | |
relationusearch_geospatial_relation_t | Which entries count as matches. | |
toleranceusearch_geospatial_tolerance_t | The radius and time slack; a zero radius ranks by distance alone. | |
matchesusearch_matches_view_t * | Output for the run, inside arena. | |
arenausearch_arena_t | Memory for matches, rewound by the call. | |
wantedsize_t | Columns per row, and the upper bound on matches - the "k" in "kANN". | |
expansion_factorsize_t | The optional breadth of the candidates a walk explores - the ef of the literature; zero derives, a scan ignores it. | |
traversalusearch_traversal_t | How entries are reached: a walk, the default, or an exact scan of every entry, on RAM and NVMe. | |
predicateusearch_predicate_t | The optional predicate, asked about a batch of candidates at a time. | |
progressusearch_progress_t | The optional handler, called with queries resolved and their count. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_unknown_kind_kArelationortraversalthis build does not know.usearch_status_unsupported_kAvisiblerelation on a handle without terrain, or a scan of a VRAM handle, or apredicateon one.
usearch_geospatial_withinReports every entry within the radius of each query observation that the relation admits - the containment counterpart of the ranked search, unbounded in result count.
void usearch_geospatial_within(usearch_geospatial_within_t *arguments); Complete on the converged graph: the walk widens its candidates by the cone graph's spanner bound before trusting it, so every candidate inside the tolerance is enumerated, at about thirty times the cost of the ball it reports. Containment sizes its own candidates from that bound, so it takes no breadth a caller could make the report incomplete with. Only the walks learn how large the report is, so the keys, scores and Apache Arrow offsets are written in arena as one ragged output, as usearch_dense_multiply writes its pairs. A predicate narrows the report without stopping the walk from crossing the entries it rejects.
A cancelled call reports usearch_status_cancelled_k and leaves the outputs NULL.
Parameters
indexusearch_geospatial_index_t | The handle to be queried. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Queries to resolve, one walk apiece. | |
queriesusearch_geospatial_observation_t const * | The count query observations. | |
relationusearch_geospatial_relation_t | Which entries count as matches. | |
toleranceusearch_geospatial_tolerance_t | The radius and time slack; metres must be positive. | |
matchesusearch_matches_tape_view_t * | Output for the report inside arena, query i spanning entries matches->offsets[i] up to matches->offsets[i+1]. | |
writtensize_t * | The optional output for the entries written across every query. | |
arenausearch_arena_t | Memory for matches, rewound by the call. | |
traversalusearch_traversal_t | How entries are reached: a complete walk, the default, or an exact scan of every entry, on RAM and NVMe. | |
predicateusearch_predicate_t | The optional predicate, asked about a batch of candidates at a time. | |
progressusearch_progress_t | The optional handler, called with queries resolved and their count. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_invalid_argument_kA tolerance of zero metres, since containment needs a radius.usearch_status_unknown_kind_kArelationortraversalthis build does not know.usearch_status_unsupported_kAvisiblerelation on a handle without terrain, or a scan of a VRAM handle, or apredicateon one.
usearch_sequence_insertAdds a tape of sequences under their keys - the native batch operation; a single sequence is a tape of one.
void usearch_sequence_insert(usearch_sequence_insert_t *arguments); An insertion is all-or-nothing per call. Every fallible step runs before the first entry identity is claimed, so a rejected call publishes nothing - a cancelled one included, which reports usearch_status_cancelled_k - and the entries of an accepted one become visible at once, their keys right after.
A key already holding values_per_key entries rejects the whole call, since a smaller retry cannot help.
Parameters
indexusearch_sequence_index_t | The handle to be populated. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Sequences to admit - the batch axis of keys and sequences. | |
keysusearch_keys_view_t | The identities to admit the sequences under, one per sequence. | |
sequencesusearch_tape_view_t | The sequences, as bytes end to end around count + 1 offsets. | |
expansion_factorsize_t | The optional breadth of the candidates the build walk explores - the ef of the literature; zero derives. | |
progressusearch_progress_t | The optional handler, called with entries admitted and the batch length. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_read_only_kThe handle is a view.
usearch_sequence_searchPerforms k-Nearest Neighbors Search for a tape of queries, approximate by walking the graph or exact by scanning every entry; one query is a tape of one.
void usearch_sequence_search(usearch_sequence_search_t *arguments); The native batch operation, parallelized internally. Never writes to the graph, so any number may overlap with concurrent insertions. Concurrency & Thread Safety
A predicate narrows the matches to the entries it admits. Non-matching entries still route the traversal rather than terminating it, so recall does not collapse at low selectivity - the walk crosses rejected regions to reach admitted ones behind them. The cost is that the predicate judges far more keys than wanted, every scored candidate, asked about a batch of them at a time, so it belongs on the caller's fast path.
A cancelled search reports usearch_status_cancelled_k and leaves matches NULL.
Parameters
indexusearch_sequence_index_t | The handle to be queried. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Queries to resolve; the outputs have count rows of wanted entries. | |
queriesusearch_tape_view_t | The queries, as bytes end to end around count + 1 offsets. | |
matchesusearch_matches_view_t * | Output for the run, inside arena. | |
arenausearch_arena_t | Memory for matches, rewound by the call. | |
wantedsize_t | Columns per row, and the upper bound on matches - the "k" in "kANN". | |
expansion_factorsize_t | The optional breadth of the candidates a walk explores - the ef of the literature; zero derives, a scan ignores it. | |
traversalusearch_traversal_t | How entries are reached: a walk, the default, or an exact scan of every entry, on RAM and NVMe. | |
predicateusearch_predicate_t | The optional predicate, asked about a batch of candidates at a time. | |
progressusearch_progress_t | The optional handler, called with queries resolved and their count. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_unknown_kind_kAtraversalother than a walk or a scan.usearch_status_unsupported_kA scan of a VRAM handle, or apredicateon one.
usearch_shapes_insertAdds a tape of shapes under their keys - the native batch operation; a single shape is a tape of one.
void usearch_shapes_insert(usearch_shapes_insert_t *arguments); Point counts may differ freely between entries. Overlaps safely with concurrent searches on the same handle. Concurrency & Thread Safety
An insertion is all-or-nothing per call. Every fallible step runs before the first entry identity is claimed, so a rejected call publishes nothing - a cancelled one included, which reports usearch_status_cancelled_k - and on a RAM handle the entries of an accepted one become visible at once.
A key already holding values_per_key entries rejects the whole call, since a smaller retry cannot help.
Parameters
indexusearch_shapes_index_t | The handle to be populated. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Shapes to admit - the batch axis of keys and shapes. | |
keysusearch_keys_view_t | The identities to admit the shapes under, one per entry and not necessarily unique. | |
shapesusearch_tape_view_t | The shapes, points end to end around count + 1 point offsets. | |
expansion_factorsize_t | The optional breadth of the candidates the build walk explores; zero derives. | |
progressusearch_progress_t | The optional handler, called with entries admitted and the batch length. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_read_only_kThe handle is a view.usearch_status_shape_mismatch_kAn entry's point count differs from a frozenpoints.
usearch_shapes_searchPerforms k-Nearest Neighbors Search for a tape of query shapes, approximate by walking the graph or exact by scanning every entry; one query is a tape of one.
void usearch_shapes_search(usearch_shapes_search_t *arguments); The native batch operation, parallelized internally. Query point counts are unconstrained and need not match any indexed entry. Never writes to the graph, so any number may overlap with concurrent insertions. Concurrency & Thread Safety
A predicate narrows the matches to the entries it admits. Non-matching entries still route the traversal, so recall does not collapse at low selectivity. hints hand each query's walk landmarks the caller already trusts, such as the matches of the same keys in a cheaper index.
A cancelled search reports usearch_status_cancelled_k and leaves matches NULL.
Parameters
indexusearch_shapes_index_t | The handle to be queried. | |
|---|---|---|
executorusearch_executor_t | The executor to fan out over; its kind must match the residency. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. | |
completionusearch_completion_t | Blocking, the default, or deferred. | |
countsize_t | Query shapes to resolve; the outputs have count rows of wanted entries. | |
queriesusearch_tape_view_t | The query shapes, as points end to end around count + 1 point offsets. | |
matchesusearch_matches_view_t * | Output for the run, inside arena. | |
arenausearch_arena_t | Memory for matches, rewound by the call. | |
wantedsize_t | Columns per row, and the upper bound on matches - the "k" in "kANN". | |
expansion_factorsize_t | The optional breadth of the candidates a walk explores; zero derives, a scan ignores it. | |
traversalusearch_traversal_t | How entries are reached: a walk, the default, or an exact scan of every entry, on RAM and NVMe. | |
predicateusearch_predicate_t | The optional predicate, asked about a batch of candidates at a time. | |
hintsusearch_matches_view_t const * | The optional keys each query's walk starts from ahead of its random landmarks, one row of counts[query] keys per query, as a search writes its matches, at most one per landmark a walk draws, a neighbor list's worth; scores are not read, a scan ignores them, and keys no entry holds are skipped and counted in stats. | |
progressusearch_progress_t | The optional handler, called with queries resolved and their count. | |
statsusearch_traversal_stats_t * | The optional traversal telemetry; NULL skips reporting. |
Statuses
usearch_status_unknown_kind_kAtraversalother than a walk or a scan.usearch_status_unsupported_kA scan of a VRAM handle, apredicateon one, orhintson any handle but a RAM one.usearch_status_invalid_argument_khintsnaming no counts, or columns but no keys.usearch_status_shape_mismatch_kA hinted query counts more keys than the hints' columns.
usearch_arena_initCreates an empty arena where executor computes, so its placement is decided once and GPU code keeps its outputs on the device without asking.
void usearch_arena_init(usearch_arena_init_t *arguments); Nothing is allocated until a call writes into it. An arena of host pages may outlive the executor that made it, keeping its own memory until it is freed; a GPU arena keeps the rule usearch_arena_t notes.
Parameters
arenausearch_arena_t * | Output for the new arena. | |
|---|---|---|
executorusearch_executor_t | The executor whose calls the arena serves, which decides where it lives; NULL serves calls on the calling thread from host pages. | |
outcomeusearch_outcome_t * | Output for the outcome, final once its status leaves usearch_status_deferred_k. |
usearch_arena_freeFrees the arena and every output in it; NULL is safe, and it cannot fail, so takes no outcome.
void usearch_arena_free(usearch_arena_t arena); Waits until every deferred call naming the handle is final, and leaves the arena to the last release of the Arrow exports still pinning it. Free a GPU arena once the caller's own device work on its outputs has finished, keeping the rule usearch_arena_t notes.
Parameters
arena | inout | The arena to be freed; invalid afterwards. |
|---|