# Metrics

> USearch for C#

### Dense Indexes

`DenseOptions` is immutable, so a variant comes from `DenseOptions.Default with { ... }` rather than from mutating a value another handle may already have been built from.

`using Cloud.Unum.USearch;`

## DenseIndex

A Vector Search Index over equidimensional dense representations.

```csharp
class DenseIndex
```

Every verb is a batch over a RowsView, so a single vector is a one-row matrix. The breadth of the candidates rides each call rather than the handle, which lets a recall sweep run against one immutable index with no mutation between points.

The receiver chooses where a verb runs, and the verb stays the same: called on the index it runs on the caller's own thread, on On it blocks on that executor, and on Deferred it submits there and answers a Deferred<TResult>. The executor's kind must match the residency of the handle.

A handle may be shared across threads, and no method here takes a lock: every output whose length scales with the call lands in an Arena the caller lends. On a RAM handle, insertions and searches overlap freely: searches read only entries published behind the visibility watermark and never write to the graph, while insertions synchronize through per-node locks and publish in order. Serialization is the one exception, demanding a mutation-free window, though concurrent readers keep searching throughout.

## InitRam

Creates an empty, mutable index in host memory, one shard per named NUMA node.

```csharp
DenseIndex InitRam(
    DenseOptions options,
    ReadOnlySpan<int> memoryDomains = default,
    CPUClass? cpuClass = null);
```

Calls `usearch_dense_init_ram`.

- `options`: The geometry and metric the index freezes.
- `memoryDomains`: NUMA node IDs to place one shard on apiece; empty derives every node the process may allocate on.
- `cpuClass`: The class the index dispatches as; null derives the CPU's own.

## InitVram

Creates an empty, mutable index in device memory, one shard per named device, sharded and never replicated.

```csharp
DenseIndex InitVram(
    DenseOptions options,
    ReadOnlySpan<int> devices = default,
    GPUClass? gpuClass = null);
```

Calls `usearch_dense_init_vram`.

- `options`: The geometry and metric the index freezes.
- `devices`: CUDA device ordinals to place one shard on apiece; empty derives one free device.
- `gpuClass`: The class the index dispatches as; null derives the devices' own.

## LoadRam

Copies a checkpoint into a new, mutable index in host memory.

```csharp
DenseIndex LoadRam(
    string path,
    ReadOnlySpan<int> memoryDomains = default,
    ulong valuesPerKey = 0,
    Executor? executor = null,
    CPUClass? cpuClass = null);
```

Point the path at a `.safegraphs.json` manifest or a single `.safegraphs` monolith; the geometry and metric come from the checkpoint's own headers. Calls `usearch_dense_load_ram`.

- `path`: The checkpoint to read.
- `memoryDomains`: Where the parts land, part `p` on shard `p` modulo the shard count; empty derives every node.
- `valuesPerKey`: The upper bound on entries sharing one key, which no checkpoint records; zero is unbounded.
- `executor`: The workers the read fans out over; null reads on the caller's thread.
- `cpuClass`: The class the index dispatches as; null derives the CPU's own.

## LoadVram

Copies a checkpoint into a new, mutable index in device memory, placing its parts as LoadRam does.

```csharp
DenseIndex LoadVram(
    string path,
    ReadOnlySpan<int> devices = default,
    ulong valuesPerKey = 0,
    Executor? executor = null,
    GPUClass? gpuClass = null);
```

Calls `usearch_dense_load_vram`.

- `path`: The checkpoint to read.
- `devices`: Where the parts land, part `p` on device `p` modulo their count; empty derives one free device.
- `valuesPerKey`: The upper bound on entries sharing one key; zero is unbounded.
- `executor`: The workers the upload runs on; null uploads on the caller's thread.
- `gpuClass`: The class the index dispatches as; null derives the devices' own.

## LoadRamBuffer

Copies a monolith from a buffer into a new, mutable index in host memory, as LoadRam does a path.

```csharp
DenseIndex LoadRamBuffer(
    ReadOnlySpan<byte> buffer,
    ReadOnlySpan<int> memoryDomains = default,
    ulong valuesPerKey = 0,
    Executor? executor = null,
    CPUClass? cpuClass = null);
```

Calls `usearch_dense_load_ram_buffer`.

- `buffer`: The monolith's bytes, copied in before the call returns.
- `memoryDomains`: The NUMA nodes to place shards on; the monolith lands whole on the first.
- `valuesPerKey`: The upper bound on entries sharing one key; zero is unbounded.
- `executor`: The workers the copy fans out over; null copies on the caller's thread.
- `cpuClass`: The class the index dispatches as; null derives the CPU's own.

## LoadVramBuffer

Copies a monolith from a buffer into a new, mutable index in device memory.

```csharp
DenseIndex LoadVramBuffer(
    ReadOnlySpan<byte> buffer,
    ReadOnlySpan<int> devices = default,
    ulong valuesPerKey = 0,
    Executor? executor = null,
    GPUClass? gpuClass = null);
```

Calls `usearch_dense_load_vram_buffer`.

- `buffer`: The monolith's bytes, in host or device memory.
- `devices`: The devices to place shards on; the monolith lands whole on the first.
- `valuesPerKey`: The upper bound on entries sharing one key; zero is unbounded.
- `executor`: The workers the upload runs on; null uploads on the caller's thread.
- `gpuClass`: The class the index dispatches as; null derives the devices' own.

## ViewRam

Serves a checkpoint in place through a memory mapping, as a read-only index whose mutating verbs report Status.ReadOnly; the files must stay unmodified while it lives.

```csharp
DenseIndex ViewRam(string path);
```

Calls `usearch_dense_view_ram`.

- `path`: The checkpoint to serve.

## ViewNvme

Serves a checkpoint in place from NVMe drives, read through the executor's submission rings, as a read-only index.

```csharp
DenseIndex ViewNvme(
    string path,
    ReadOnlySpan<string> paths = default,
    Executor? executor = null,
    CPUClass? cpuClass = null);
```

External-memory graphs are never modified in place, so every mutating verb fails on it with Status.ReadOnly. Calls `usearch_dense_view_nvme`.

Until NVMe checkpoints carry keys, the engine answers Status.Unsupported.

- `path`: The checkpoint to serve.
- `paths`: The devices the parts are served from; empty serves each where its manifest points.
- `executor`: The NVMe executor whose rings read the headers; null reads on the caller's thread.
- `cpuClass`: The class the index dispatches as; null derives the CPU's own.

## MetadataRead

Reads a checkpoint's geometry and metric metadata without loading it - from the manifest's summary when the path names one, so no shard is opened.

```csharp
DenseMetadata MetadataRead(string path, Executor? executor = null);
```

Calls `usearch_dense_metadata_read`.

- `path`: The checkpoint path.
- `executor`: The workers the read runs on; null reads on the caller's thread.

## MetadataReadBuffer

Reads geometry and metric metadata from a serialized monolith buffer.

```csharp
DenseMetadata MetadataReadBuffer(
    ReadOnlySpan<byte> buffer,
    Executor? executor = null);
```

Calls `usearch_dense_metadata_read_buffer`.

- `buffer`: The monolith's bytes.
- `executor`: The workers the read runs on; null reads on the caller's thread.

## On

The receiver whose verbs block on _executor_ , after every call submitted there before them.

```csharp
DenseIndexOn On(Executor executor);
```

Binding-only.

- `executor`: The executor the verbs run on.

## Deferred

The receiver whose verbs submit their calls to _executor_  and answer a Deferred<TResult> at once.

```csharp
DenseIndexDeferredOn Deferred(Executor executor);
```

Binding-only.

- `executor`: The executor the calls are submitted to.

## Reserve

Claims capacity for incoming vectors, counting the entries already stored - a hint, since insertions grow the index on demand.

```csharp
void Reserve(ulong capacity);
```

Calls `usearch_dense_reserve`.

- `capacity`: The desired total capacity.

## Clear

Erases all entries, keeping the reserved capacity and the frozen geometry; no other call on the handle may overlap it.

```csharp
void Clear();
```

Calls `usearch_dense_clear`.

## Describe

Reports the frozen metadata and the current counters in one call.

```csharp
DenseIndexDescription Describe();
```

Calls `usearch_dense_describe`.

## Count

Counts the entries stored under a key; zero means the index holds none.

```csharp
ulong Count(Key key);
```

Calls `usearch_dense_count`.

- `key`: The identity to look for.

## Contains

Reports whether the index holds at least one entry under a key.

```csharp
bool Contains(Key key);
```

Calls `usearch_dense_count`.

- `key`: The identity to look for.

## Get

Retrieves every vector stored under a key, one row per entry sharing the key, in insertion order, converted to the kind asked for and as wide as the library reports.

```csharp
DenseVectors Get(
    Key key,
    Arena arena,
    Scalar outputsScalar = Scalar.F32);
```

Calls `usearch_dense_get`.

- `key`: The identity to look for.
- `arena`: Where the rows land, rewound by the call.
- `outputsScalar`: The scalar type to export as.

## Insert

Inserts a matrix of vectors under their keys - the native batch operation, which overlaps safely with concurrent searches on the same handle.

```csharp
void Insert(
    ReadOnlyMemory<Key> keys,
    RowsView vectors,
    ulong expansionFactor = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_insert`.

The input scalar type is independent of the stored quantization; the library converts on ingest. A batch is all-or-nothing: every fallible step runs before the first entry identity is claimed, so a rejected batch publishes nothing.

- `keys`: One identity per row.
- `vectors`: The rows to admit.
- `expansionFactor`: The breadth of the candidates the build walk explores; zero derives it from the geometry.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Refine

Re-selects the neighbors of every stored entry against the finished graph, improving edges that were chosen when the graph around them was still incomplete.

```csharp
RefineReport Refine(
    ulong expansionFactor = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_refine`.

This is a build step rather than a repair: a cheap insertion pass followed by one refinement reaches a better graph, in less total time, than a single expensive insertion pass - so a wide expansion factor belongs here rather than in Insert. Searches may run throughout, since edge re-selection publishes one neighbor list at a time and never removes a node.

- `expansionFactor`: The breadth of the candidates the re-selection walk explores; zero derives it from the geometry.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Health

Audits how much of the graph a search can reach: forward reachability from as many landmarks as one search draws, swept level by level.

```csharp
DenseReachability Health();
```

Read-only, so concurrent insertions merely leave fresh entries unaudited. Calls `usearch_dense_health`.

## Search

Resolves a matrix of queries into the nearest entries - the native batch operation, parallelized internally, which never writes to the graph.

```csharp
Matches Search(
    RowsView queries,
    int wanted,
    Arena arena,
    ulong expansionFactor = 0,
    Func<Key, bool>? predicate = null,
    DenseTraversalStats? stats = null,
    Traversal traversal = Traversal.Walk);
```

Calls `usearch_dense_search`.

A predicate narrows the matches to the keys it admits; rejected entries still route the traversal, so recall does not collapse at low selectivity. It runs on the executor's worker threads, so it must be safe for concurrent use, and it is called once per scored candidate rather than once per reported match. An exception it throws cannot cross the boundary: the first one is captured, every later candidate is rejected, and the exception is rethrown once the call is final.

- `queries`: The query rows, one query apiece.
- `wanted`: The upper bound on matches per query - the "k" in kANN.
- `arena`: Where the run lands, rewound by the call.
- `expansionFactor`: The breadth of the candidates the walk explores; zero derives it from the geometry.
- `predicate`: The per-key admission predicate; null admits every key. A host predicate cannot narrow a device walk, so a VRAM handle refuses one as Status.Device.
- `stats`: The traversal telemetry to fill, when the caller wants any.
- `traversal`: A walk, the default, or an exact scan of every entry on RAM and NVMe handles; a VRAM handle refuses a scan as Status.Unsupported.

## Maxsim

Scores multi-row queries against multi-row entries by late interaction: every query row takes its best match within a key, and those maxima sum to that key's score.

```csharp
DenseProducts Maxsim(
    RowsView queries,
    int rowsPerQuery,
    int wanted,
    Arena arena,
    ulong expansionFactor = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_maxsim`.

A document is one key holding its token rows, so this is what a values-per-key bound above one exists for. It runs on the inner-product kinds alone, since a maximum over logits is what late interaction sums, and a graph frozen under a distance kind refuses with Status.ConfigMismatch.

- `queries`: The token rows of every query, laid end to end.
- `rowsPerQuery`: The rows in every query; uniform, so the row count must be a whole multiple of it and the quotient is the query count.
- `wanted`: The upper bound on documents per query - the "k" over documents rather than over rows; zero keeps every key the query scored.
- `arena`: Where the scored keys and their offsets land, rewound by the call.
- `expansionFactor`: The breadth of the candidates the walk explores; zero derives it from the geometry.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Multiply

Multiplies a run of rows against the indexed vectors, reporting every pair the traversal scored rather than only the nearest - the approximate sparse product a graph walk reads off for free.

```csharp
DenseProducts Multiply(
    RowsView left,
    Arena arena,
    ulong wanted = 0,
    ulong expansionFactor = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_multiply`.

Pairs arrive in traversal order, without duplicates, and the pairs the walk never reaches are the low and negative products. Runs on the inner-product kinds alone; a graph frozen under a distance kind refuses with Status.ConfigMismatch.

- `left`: The left-hand rows, one walk apiece.
- `arena`: Where the pairs and their offsets land, rewound by the call.
- `wanted`: The bound on pairs kept per row, the first ones its walk scored; zero keeps every pair.
- `expansionFactor`: The breadth of the candidates, which widens the emitted pattern; zero derives it from the geometry.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Attend

Softmax attention of a run of query heads over every indexed key their graph walks score, folded as Flash Attention folds key tiles, with no top-k cut.

```csharp
DenseVectors Attend(
    RowsView queries,
    RowsView values,
    Func<Key, int> rowOf,
    Arena arena,
    ulong headCount = 0,
    Memory<DenseSoftmaxState> carry = default,
    Scalar outputsScalar = Scalar.Unknown,
    ulong expansionFactor = 0,
    float scoreScale = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_attend`.

The index stores no values, so every scored key resolves to a row of _values_  through _rowOf_ , which runs on the executor's threads together. A key resolving outside it, or a values matrix of another scalar kind or width than the index's own, refuses the call with Status.ShapeMismatch, since a missing row is a wrong softmax rather than a smaller one. Runs on the inner-product kinds alone; a graph frozen under a distance kind refuses with Status.ConfigMismatch. _rowOf_  is a host function, so it serves RAM handles alone: a VRAM walk resolves rows through a device function, which this binding does not build, so an attention into a Residency.Vram arena refuses with Status.Device.

- `queries`: The query rows; row `t * headCount + h` is head `h` of token `t`.
- `values`: The value rows the scored keys resolve into, pinned for the call.
- `rowOf`: Resolves a key to its row of _values_ .
- `arena`: Where the attended rows land, already divided by the partition, rewound by the call.
- `headCount`: The query heads sharing one walk per token; it must divide the query count, and zero means one.
- `carry`: The online-softmax state, one per query row, which merges this branch with another over the same queries; empty skips it.
- `outputsScalar`: The scalar type the attended rows land as; Scalar.Unknown takes the queries' own.
- `expansionFactor`: The breadth of the candidates; zero derives it from the geometry.
- `scoreScale`: The logit scale; zero derives the inverse square root of the dimensionality.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Absorb

Absorbs every donor into this index, one after another, keeping their graphs rather than re-inserting their vectors and linking each in across the appended part.

```csharp
RefineReport Absorb(params DenseIndex[] donors);
```

Calls `usearch_dense_absorb`.

An absorbed donor is consumed and refuses every later verb with Status.Uninitialized; one the call did not absorb, such as a donor of another residency, scalar, metric or geometry, which refuses with Status.ConfigMismatch, stays a live index the caller still owns, though its entries may already have moved here.

- `donors`: The indexes to absorb.

## Split

Splits this index into the empty receivers, the inverse of Absorb: the entries are partitioned along the graph, each part lands in one receiver with its edges kept, and a closing refinement re-links every receiver, leaving this index empty and live.

```csharp
RefineReport Split(
    DenseIndex[] receivers,
    ulong seed = 0,
    ulong expansionFactor = 0,
    DenseTraversalStats? stats = null);
```

Calls `usearch_dense_split`.

- `receivers`: At least two empty indexes of this one's residency, scalar, metric, geometry and shard count.
- `seed`: Picks the part roots: equal seeds over an unchanged index split equally.
- `expansionFactor`: The breadth of the closing walks; zero derives it.
- `stats`: The traversal telemetry to fill, when the caller wants any.

## Sample

Draws keys around the focus, or across the whole index, each hanging from a shown or earlier draw and placed in three dimensions beside the shown ones - so a view grows one connected sample as it zooms.

```csharp
Sample Sample(
    int wanted,
    Arena arena,
    DenseSampleConfig config = default);
```

A larger _wanted_  under the same seed draws a superset; only a RAM index samples yet. Calls `usearch_dense_sample`.

- `wanted`: The upper bound on draws.
- `arena`: Where the draws are written, rewound by the call.
- `config`: The keys shown and their coordinates, the focus, the seed and the walk.

## Save

Writes the index under a path, in the layout its extension picks - one `.safegraphs` monolith, or a `.safegraphs.json` manifest beside its shards.

```csharp
void Save(string path);
```

Demands a mutation-free window; concurrent readers keep searching throughout. Calls `usearch_dense_save`.

- `path`: Where the checkpoint is written.

## SaveBuffer

Writes the index as one monolith, the same bytes Save writes to a `.safegraphs` path.

```csharp
Monolith SaveBuffer(Arena arena);
```

Calls `usearch_dense_save_buffer`.

- `arena`: Where the bytes land, rewound by the call.

## Cursor

Opens a walk over the current contents, pulled on the caller's thread; each shard's publication watermark is read as the walk enters it, so an entry once passed is never revisited.

```csharp
DenseCursor Cursor(ReadOnlySpan<Key> starts = default);
```

Without starts it yields every entry as stored; with them, the start keys' own entries first in order, then the entries those link to breadth-first, each once. Calls `usearch_dense_cursor_init`.

- `starts`: The keys to walk from; empty walks every row.

## SearchStream

Opens a resumable nearest-neighbor stream for one query, pulled on the caller's thread.

```csharp
DenseSearchStream SearchStream(
    RowsView query,
    ulong expansionFactor = 0);
```

The stream keeps walk state rather than a thread. Calls `usearch_dense_search_stream_init`.

- `query`: The single query row, whose row count must be one.
- `expansionFactor`: The breadth of the candidates the walk explores; zero derives it from the geometry.

## Dispose

Releases the index, once every deferred call naming it is final.

```csharp
void Dispose();
```

Freeing cannot fail, and a freed handle must not be used. Calls `usearch_dense_free`.

