# Inputs and Outputs

> USearch for Zig

### Arenas

Every output whose length only the call knows, such as matches, rows, products, monoliths and cursor or stream batches, lands in an `Arena` you pass, and the verb answers a view over it without copying.
`Arena.init(executor)` places it where that executor computes, decided once, and `Arena.init(null)` makes host pages for the calling thread.
Each call rewinds its arena and grows it only past its high-water mark, so the previous call's views die and a steady loop allocates once.
To keep a result past the next call, or to read one while making the next, pass that call another arena.
An arena serves one call at a time, so each deferred call needs its own.
Views find their arena by address, so it must not move while they live, and a stale view answers `Error.Uninitialized`; slices an accessor already returned are not checked again.
An arena from a VRAM executor holds device memory, which host accessors refuse with `Error.Device`.
It grows and frees on that executor's stream, so it serves only calls on that executor, any other answering `Error.Device`, and is freed before it; host pages may outlive theirs.

```zig
var arena = try usearch.Arena.init(executor); // `Arena.init(null)` is host pages for the calling thread
defer arena.deinit();
for (batches) |batch| {
    const matches = try index.on(executor).search(batch, 10, &arena, .{}); // rewinds: the last batch's matches are gone
    total += (try matches.query(0)).scores[0];
}

var found = try usearch.Arena.init(null); // two live results, two arenas
defer found.deinit();
var fetched = try usearch.Arena.init(null);
defer fetched.deinit();
const nearest = try index.search(query, 10, &found, .{});
for ((try nearest.query(0)).keys) |key| rerank(key, try index.get(key, .f32, &fetched));

var calls: [shards.len]usearch.Deferred(usearch.DenseSearch) = undefined;
for (&calls, shards, executors, &arenas) |*call, shard, pool, *own|
    try shard.deferred(pool, call).search(queries, 10, own, .{}); // one executor and one arena per submitted call
defer for (&calls) |*call| call.deinit();
for (&calls) |*call| consume(try call.wait());
```

A call that finds its arena serving another call finishes with `Error.Contended` and rewinds nothing, so the holder's views stay readable.
A call that fails for any other reason still rewinds it.
Only fixed-size reports like `DenseTraversalStats` stay your fields.

### Rows & Scalars

Every batch input is a run of rows given by a base pointer, a row count, a column count, and a byte stride, so a memory-mapped dataset feeds the index with no reshape and no copy.
The scalar type of the input is independent of the stored quantization, so the `f32` slab of the Quickstart lands in an `i8` index and nothing needs converting before insertion.
`RowsView.of` reads a packed slab; a dataset whose rows are padded to a wider pitch fills the struct directly, setting `stride` to the pitch; a zero `stride` repeats the first row for every one of them.
The encodings Zig has no primitive for, `usearch.Scalar.BF16`, `E5M2`, `E4M3`, `E3M2`, `E2M3`, and the packed `I4x2`, `U4x2` and `U1x8`, travel as their raw bits, and a packed kind counts columns in dimensions, so 128 dimensions of `Scalar.U1x8` take sixteen values a row.
Lengths that cannot be read as a whole number of rows are refused with `Error.ShapeMismatch` rather than asserted, so the check survives `ReleaseFast`.
The column count travels with the rows, and the engine refuses one that differs from the frozen geometry with the same error.

Every metric derives from a single inner-product kernel with pre-computed magnitudes.

- `.inner`: inner product, and the only kind the linear-algebra verbs accept.
- `.angular`: cosine distance, over pre-computed magnitudes.
- `.euclidean`: L2 distance.
- `.hamming`: bit-level, over `.u1x8` vectors alone.
- `.jaccard`: bit-level, over `.u1x8` vectors alone.

Arbitrary metrics belong to the C++ baseline tier; the C interface, and so this module, takes the built-in kinds alone.

### Search

Every verb has one entry point, its optional knobs riding one config struct named after its C argument structure, such as `DenseSearchConfig`, `DenseInsertConfig` or `DenseMultiplyConfig`.

```zig
var arena = try usearch.Arena.init(executor);
defer arena.deinit();
var stats: usearch.DenseTraversalStats = .{};

const matches = try index.on(executor).search(try .of(f32, queries, 768), 10, &arena, .{
    .expansion_factor = 128,
    .stats = &stats,
});
for (0..matches.queries) |query| consume(try matches.query(query));
std.debug.print("{d} distances computed\n", .{stats.computed_distances});
```

`Matches.query` answers one query's keys and distances, nearest first, as many as the walk found up to the "k" asked for.

The breadth of the candidates rides the call rather than the handle, so a recall sweep is a loop over expansion factors against one immutable index, with no mutation and no synchronization between points.
`.traversal = .scan` scores every entry instead of walking, on RAM and NVMe handles, which gives that sweep its exact ground truth; a VRAM handle answers it with `Error.Unsupported`.

`const usearch = @import("usearch");`

`const Scalar = @import("usearch").Scalar;`

`const Traversal = @import("usearch").Traversal;`

`const RowsView = @import("usearch").RowsView;`

`const Matches = @import("usearch").Matches;`

`const Arena = @import("usearch").Arena;`

## QueryMatches

The matches of one query: nearest first for a search, largest first for a [`maxsim`](https://www.unum.cloud/docs/usearch/zig/metrics.md#maxsim), and in traversal order for a [`multiply`](https://www.unum.cloud/docs/usearch/zig/metrics.md#multiply).

```zig
pub const QueryMatches = struct
```

Binding-only.

- `keys` `[]const Key`: The keys written for the query.
- `scores` `[]const Distance`: Positionally paired with [`keys`](https://www.unum.cloud/docs/usearch/zig/retrieval-and-streaming.md#keys): distances for a search, similarities for the linear-algebra verbs.

## DenseTraversalStats

Traversal telemetry, fully overwritten by the call it is passed to.

```zig
pub const DenseTraversalStats = extern struct
```

Mirrors `usearch_traversal_stats_t`.

- `visited_members` `usize`: Graph members visited while resolving the batch.
- `computed_distances` `usize`: Distances computed while resolving the batch, diversity re-selections included.
- `restarts` `usize`: Starvation restarts - a graph-connectivity health signal rather than a cost counter.
- `missing_hints` `usize`: Hint keys no shard held an entry under; zero unless a search was handed hints.

## DenseInsertConfig

Optional settings of [`DenseIndex.insert`](https://www.unum.cloud/docs/usearch/zig/metrics.md#insert).

```zig
pub const DenseInsertConfig = struct
```

- `expansion_factor` `usize`: The breadth of the candidates the build walk explores; zero derives.
- `progress` `ProgressCallback`: Called with entries admitted; it reports and cannot cancel, since every entry is claimed first.
- `progress_steps` `usize`: Reports the call makes at most, the last at completion; zero derives to ten.
- `stats` `?*DenseTraversalStats`

## DenseSearchConfig

Optional settings of [`DenseIndex.search`](https://www.unum.cloud/docs/usearch/zig/metrics.md#search).

```zig
pub const DenseSearchConfig = struct
```

- `expansion_factor` `usize`: The breadth of the candidates the walk explores; zero derives.
- `traversal` `Traversal`: A walk, or an exact scan of every entry on RAM and NVMe handles; VRAM answers [`Error.Unsupported`](https://www.unum.cloud/docs/usearch/zig/errors.md#Unsupported).
- `predicate` `Predicate`: Admits only the keys it approves; non-matching entries still route the walk. Refused on VRAM.
- `progress` `ProgressCallback`: Called with queries resolved; a stopped search answers [`Error.Cancelled`](https://www.unum.cloud/docs/usearch/zig/errors.md#Cancelled) and no matches.
- `progress_steps` `usize`: Reports the call makes at most, the last at completion; zero derives to ten.
- `stats` `?*DenseTraversalStats`

## DenseInsert

One [`DenseIndex.insert`](https://www.unum.cloud/docs/usearch/zig/metrics.md#insert), as a [`Deferred`](https://www.unum.cloud/docs/usearch/zig/executors.md#Deferred) holds it.

```zig
pub const DenseInsert = struct
```

- `keys` `[]const Key`
- `vectors` `RowsView`
- `config` `DenseInsertConfig`
- `outcome` `Outcome`

## DenseSearch

One [`DenseIndex.search`](https://www.unum.cloud/docs/usearch/zig/metrics.md#search), as a [`Deferred`](https://www.unum.cloud/docs/usearch/zig/executors.md#Deferred) holds it.

```zig
pub const DenseSearch = struct
```

- `queries` `RowsView`
- `wanted` `usize`
- `config` `DenseSearchConfig`
- `stamp` `Arena.Stamp`: The call the borrowed arena serves, which every view over the outputs carries.
- `matches` `usearch_matches_view_t`
- `outcome` `Outcome`

## Scalar

Scalar types the indexes store and exchange, named by width and encoding.

```zig
pub const Scalar = enum(c_int)
```

Sub-byte types pack
several dimensions per byte, as their `xN` suffixes spell.

Non-exhaustive, so an encoding a newer engine reports arrives intact rather than coerced.

- `unknown` = `0`: No scalar named - an unset field, or a custom metric owning its own storage.
- `f64` = `1`: IEEE-754 binary64.
- `f32` = `2`: IEEE-754 binary32.
- `bf16` = `3`: Truncated f32 - 8-bit exponent, 7-bit mantissa.
- `f16` = `4`: IEEE-754 binary16.
- `e5m2` = `5`: FP8 with a 5-bit exponent.
- `e4m3` = `6`: FP8 with a 4-bit exponent.
- `e3m2` = `7`: FP6 with a 3-bit exponent, byte-aligned with two padding bits.
- `e2m3` = `8`: FP6 with a 2-bit exponent, byte-aligned with two padding bits.
- `i8` = `10`: 8-bit signed integer.
- `i4x2` = `11`: Two signed nibbles per byte, even dimensions low.
- `i32` = `12`: 32-bit signed integer - the coordinates of geospatial points.
- `u8` = `20`: 8-bit unsigned integer.
- `u4x2` = `21`: Two unsigned nibbles per byte, even dimensions low.
- `u1x8` = `22`: Eight single-bit dimensions per byte - what Hamming and Jaccard score.

## BF16

The raw bits of one `.bf16` value, for the encodings Zig has no primitive for.

```zig
pub const BF16 = extern struct
```

- `bits` `u16`

## E5M2

The raw bits of one `.e5m2` value.

```zig
pub const E5M2 = extern struct
```

- `bits` `u8`

## E4M3

The raw bits of one `.e4m3` value.

```zig
pub const E4M3 = extern struct
```

- `bits` `u8`

## E3M2

The raw bits of one `.e3m2` value, two padding bits high.

```zig
pub const E3M2 = extern struct
```

- `bits` `u8`

## E2M3

The raw bits of one `.e2m3` value, two padding bits high.

```zig
pub const E2M3 = extern struct
```

- `bits` `u8`

## I4x2

Two signed nibbles of `.i4x2`, the even dimension low.

```zig
pub const I4x2 = extern struct
```

- `bits` `u8`

## U4x2

Two unsigned nibbles of `.u4x2`, the even dimension low.

```zig
pub const U4x2 = extern struct
```

- `bits` `u8`

## U1x8

Eight single-bit dimensions of `.u1x8`, the first one lowest.

```zig
pub const U1x8 = extern struct
```

- `bits` `u8`

## of

The encoding a Zig element type stores as: a primitive, or one of the raw-bit types above.

```zig
pub fn of(comptime Element: type) Scalar
```

## dimensionsPerValue

Logical dimensions one stored value carries: more than one for the packed kinds.

```zig
pub fn dimensionsPerValue(self: Scalar) usize
```

Binding-only.

## name

The canonical spelling, as `.f32` spells "f32".

```zig
pub fn name(self: Scalar) [:0]const u8
```

Calls `usearch_scalar_name`.

## fromName

Reads a spelling back, or null when no kind spells it.

```zig
pub fn fromName(text: []const u8) ?Scalar
```

Calls `usearch_scalar_from_name`.

## Traversal

How a search reaches the indexed entries it scores.

```zig
pub const Traversal = enum(c_int)
```

Mirrors `usearch_traversal_t`.

- `walk` = `1`: Walk the graph, scoring the entries the expansion reaches - approximate, the default.
- `scan` = `2`: Score every entry published when the query's scan starts - exact, on RAM and NVMe handles.

## name

The canonical spelling, as `.scan` spells "scan".

```zig
pub fn name(self: Traversal) [:0]const u8
```

Calls `usearch_traversal_name`.

## fromName

Reads a spelling back, or null when no traversal spells it.

```zig
pub fn fromName(text: []const u8) ?Traversal
```

Calls `usearch_traversal_from_name`.

## RowsView

A borrowed run of rows - the batch currency every modality's row inputs take, mirroring `usearch_rows_view_t` with the row count it leaves to the call.

```zig
pub const RowsView = struct
```

One vector is a one-row run, so a caller never packs a special case. `rows` is the batch axis a
verb passes on as its count, and `columns` travels with the rows for the engine to check
against the frozen geometry. A zero `stride` repeats the first row.

- `data` `?*const anyopaque`: Base pointer of the first row.
- `rows` `usize`: Rows the run carries.
- `columns` `usize`: Logical scalars per row, as the caller counts them - dimensions, never bytes.
- `stride` `usize`: Bytes between the starts of consecutive rows; zero repeats the first row.
- `scalar` `Scalar`: The scalar type the rows hold, converted on the way in where it differs.

## of

Reads a contiguous slab as rows of `columns` dimensions, which a packed kind counts in dimensions rather than values, so 128 dimensions of [`Scalar.U1x8`](#U1x8) take sixteen values a row.

```zig
pub fn of(
    comptime Element: type,
    data: []const Element,
    columns: usize,
) Error!RowsView
```

A zero column count, a width that does not fill whole values, or a slab that is not a whole
number of rows is a shape the engine would refuse too, so it is refused here rather than
divided by.

## ofRow

Reads one contiguous vector as a one-row run; an empty vector is no row at all.

```zig
pub fn ofRow(
    comptime Element: type,
    data: []const Element,
) Error!RowsView
```

## Matches

The ranked matches a search or a stream pull wrote into an arena, one list per query, each holding up to the `wanted` the call asked for.

```zig
pub const Matches = struct
```

Mirrors `usearch_matches_view_t`.

It reads the arena, so every read is refused once that arena serves another call or is freed.

- `stamp` `Arena.Stamp`
- `view` `usearch_matches_view_t`
- `queries` `usize`: Queries the call resolved.

## query

The matches written for one query, refusing a `position` past `queries` with [`Error.InvalidArgument`](https://www.unum.cloud/docs/usearch/zig/errors.md#InvalidArgument), a stale view with [`Error.Uninitialized`](https://www.unum.cloud/docs/usearch/zig/errors.md#Uninitialized), and device memory with [`Error.Device`](https://www.unum.cloud/docs/usearch/zig/errors.md#Device).

```zig
pub fn query(self: Matches, position: usize) Error!QueryMatches
```

## residency

Where the matches live, which the host reads only as `.ram` or `.nvme`.

```zig
pub fn residency(self: Matches) Residency
```

## Arena

Memory the library writes every output whose length scales with a call into - matches, rows, products, monoliths and cursor batches - mirroring `usearch_arena_t`.

```zig
pub const Arena = struct
```

Every verb writing such outputs borrows one as `*Arena`, blocking or deferred alike. Each call
rewinds it, so the views of the previous call refuse every read afterwards, and refills it,
growing only past its high-water mark, so a steady loop allocates once. An arena serves one call
at a time: a second use while a call holds it fails with [`Error.Contended`](https://www.unum.cloud/docs/usearch/zig/errors.md#Contended) and leaves that call's
views alone. A view finds its arena where the call left it, so an arena stays put, never copied,
while views over it live.

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, any other or none answering [`Error.Device`](https://www.unum.cloud/docs/usearch/zig/errors.md#Device), and must be
freed before that executor is.

- `handle` `?*anyopaque`: The opaque `usearch_arena_t` the ABI hands back; null once freed.
- `residency` `Residency`: The residency of the executor that made it: host pages, or a GPU's memory as `.vram`.
- `generation` `usize`: Calls it has served, which every view compares against its own. Binding-only.

## init

Makes an arena where `executor` computes, decided once, or host pages for calls on the calling thread when null; host pages may outlive the executor, a GPU arena may not.

```zig
pub fn init(executor: ?Executor) Error!Arena
```

Calls `usearch_arena_init`.

## deinit

Frees every output in it, waiting for every deferred call naming it, and leaves every view over it refusing reads.

```zig
pub fn deinit(self: *Arena) void
```

Calls `usearch_arena_free`.

## Stamp

The arena and call a view was written by.

```zig
pub const Stamp = struct
```

Binding-only.

- `arena` `*const Arena`
- `generation` `usize`

## Stamp.check

Refuses a read once the arena served another call or was freed with [`Error.Uninitialized`](https://www.unum.cloud/docs/usearch/zig/errors.md#Uninitialized), and a read of device memory with [`Error.Device`](https://www.unum.cloud/docs/usearch/zig/errors.md#Device).

```zig
pub fn check(self: Stamp) Error!void
```

