# Metrics

> USearch for Mojo

### Dense Indexes

`DenseOptions` freezes an index's geometry: its dimensions, metric, quantization, connectivity and `values_per_key`, angular over `BF16` vectors unless told otherwise, with every zeroed optional field derived.
`DenseMetric` names `INNER`, `ANGULAR`, `EUCLIDEAN`, `HAMMING` and `JACCARD`; the last two read vectors as `ScalarKind.U1X8` bit sets and refuse any other quantization.
Insertions and searches overlap freely on one handle: a search never writes to the graph, and an insertion publishes an entry only once it is reachable.
`multiply`, `maxsim` and `attend` treat the index as a sparse operand, folding their arithmetic into the walk instead of materializing a match list, and need logits rather than distances, so they run on `DenseMetric.INNER` alone and refuse other metrics with `Status.CONFIG_MISMATCH`.

`from usearch import DenseMetric, DenseOptions, DenseIndex`

## Distance

A distance or similarity score in the metric of the index that produced it - `usearch_distance_t`.

```mojo
comptime Distance = Float64
```

## DenseMetric

The built-in dense metrics - `usearch_dense_metric_t`, each with its own SIMD kernel chain.

```mojo
struct DenseMetric
```

The last two read their rows as [`ScalarKind.U1X8`](https://www.unum.cloud/docs/usearch/mojo/inputs-and-outputs.md#U1X8) bit sets and refuse any other quantization; the
first four refuse that one. The three linear-algebra verbs run on [`INNER`](#INNER) alone, since a
product and a softmax both need logits rather than distances. [`Library.dense_metric_name`](https://www.unum.cloud/docs/usearch/mojo/introspection.md#dense_metric_name) spells
each one as the engine does.

- `UNKNOWN` = `DenseMetric(Int32(0))`: No kind named - an unset field, refused by every constructor.
- `INNER` = `DenseMetric(Int32(1))`: Sum of elementwise products, unnormalized and scale-sensitive.
- `ANGULAR` = `DenseMetric(Int32(2))`: Cosine distance in [0, 2], blind to magnitude.
- `EUCLIDEAN` = `DenseMetric(Int32(3))`: L2 distance, zero only for identical vectors.
- `HAMMING` = `DenseMetric(Int32(4))`: Count of differing bits, so its range is the dimensionality.
- `JACCARD` = `DenseMetric(Int32(5))`: Differing bits over union bits in [0, 1], ignoring the zeros both vectors share.
- `code` `c_int`: The raw `usearch_dense_metric_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## DenseOptions

The geometry an empty index freezes - what `usearch_dense_init_ram_t` and `usearch_dense_init_vram_t` share, without the placement each names its own way.

```mojo
struct DenseOptions
```

Zeroed optional fields derive from the geometry.

- `metric` `DenseMetric`: The metric kind used for distance calculations between vectors.
- `quantization` `ScalarKind`: The scalar type vectors are stored and quantized into.
- `dimensions` `c_size_t`: Dimensions in the indexed vectors.
- `connectivity` `c_size_t`: The connections-per-node bound; zero derives.
- `values_per_key` `c_size_t`: Upper bound on entries sharing one key; zero is unbounded.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## __init__

Describes an index by its geometry, angular over [`BF16`](https://www.unum.cloud/docs/usearch/mojo/inputs-and-outputs.md#BF16) vectors unless told otherwise.

```mojo
def __init__(
    out self,
    dimensions: Int,
    metric: DenseMetric = DenseMetric.ANGULAR,
    quantization: ScalarKind = ScalarKind.BF16,
    connectivity: Int = Int(0),
    values_per_key: Int = Int(0)
)
```

- `dimensions`: Dimensions per vector.
- `metric`: The metric kind the graph is frozen under.
- `quantization`: The scalar type vectors are stored as.
- `connectivity`: The connections-per-node bound; zero derives.
- `values_per_key`: Upper bound on entries sharing one key; zero is unbounded.

## DenseIndex

A dense vector index, released when it goes out of scope.

```mojo
struct DenseIndex
```

Insertions and searches overlap freely on one handle: a search never writes to the graph, and
an insertion publishes an entry only once it is reachable, so a concurrent walk sees a consistent
graph at every instant. Calls on one executor run in submission order.

Verbs called on the index run on the calling thread; `index.on(executor)` runs the same verbs
blocking on an executor, and `index.deferred(executor)` submits them there. The cursor and the
stream's opening name no executor, and their pulls run on the receiver's.

- `library` `Library`: The loaded engine, held so its symbol table outlives every call made through the handle.
- `address` `Address`: The opaque `usearch_dense_index_t`, or zero once an absorb has consumed it.

Conforms to: `Deinitable`, `[DenseVerbs](https://www.unum.cloud/docs/usearch/mojo/executors.md#DenseVerbs)`, `Movable`

## __init__

Adopts a handle the engine just created.

```mojo
def __init__(out self, *, library: Library, address: Int)
```

- `library`: The loaded engine the handle was created through, and is freed through.
- `address`: A `usearch_dense_index_t` whose lifetime this index takes over.

## __deinit__

Releases the index and everything it owns, unless an absorb already took the handle. Calls `usearch_dense_free`.

```mojo
def __deinit__(deinit self)
```

The loader reference is surrendered only after the call: reading the entry point is the
last use of `library`, so without the trailing move Mojo drops the last reference - and
`dlclose`s the engine - between the load and the branch to it.

## init_ram

Initializes an empty, mutable index in host memory. Calls `usearch_dense_init_ram`.

```mojo
def init_ram[ram_origin: ImmOrigin, //](
    library: Library,
    options: DenseOptions,
    ram: RamOptions[ram_origin] = RamOptions()
) -> Self
```

- `ram_origin` (comptime): The options' borrowed node-id array, inferred from the argument.
- `library`: The loaded engine, kept so the shared object stays mapped.
- `options`: The geometry and metric; read only during this call.
- `ram`: The memory domains to place one shard on apiece.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the geometry is refused, the placement cannot be resolved, or the allocation fails.

## init_vram

Initializes an empty, mutable index in device memory. Calls `usearch_dense_init_vram`.

```mojo
def init_vram[vram_origin: ImmOrigin, //](
    library: Library,
    options: DenseOptions,
    vram: VramOptions[vram_origin] = VramOptions()
) -> Self
```

- `vram_origin` (comptime): The options' borrowed ordinal array, inferred from the argument.
- `library`: The loaded engine, kept so the shared object stays mapped.
- `options`: The geometry and metric; read only during this call.
- `vram`: The devices to place one shard on apiece.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the geometry is refused, or a device cannot be selected or claimed.

## load_ram

Copies a checkpoint into a new, mutable index in host memory, shard by shard. Calls `usearch_dense_load_ram`.

```mojo
def load_ram[path_origin: ImmOrigin, ram_origin: ImmOrigin, //](
    executor: Executor,
    path: StringSpan[path_origin],
    ram: RamOptions[ram_origin] = RamOptions(),
    values_per_key: Int = Int(0)
) -> Self
```

Point the path at the manifest, never at one of the parts it enumerates - naming a part
loads exactly that part, which is a fragment of the index rather than the index. Part `p`
lands whole on shard `p` modulo the shard count, wherever it was written from.

- `path_origin` (comptime): The path bytes' origin, inferred from the argument.
- `ram_origin` (comptime): The options' borrowed node-id array, inferred from the argument.
- `executor`: The executor the read fans out over, one shard per thread; it also lends its engine.
- `path`: The manifest of a sharded checkpoint, or a single `.safegraphs` monolith.
- `ram`: The memory domains to place the parts on.
- `values_per_key`: Upper bound on entries sharing one key, which no checkpoint records.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the checkpoint cannot be read or decoded.

## load_ram_buffer

Copies a monolith from a memory buffer into a new, mutable index in host memory. Calls `usearch_dense_load_ram_buffer`.

```mojo
def load_ram_buffer[buffer_origin: ImmOrigin, ram_origin: ImmOrigin, //](
    executor: Executor,
    buffer: Span[UInt8, buffer_origin],
    ram: RamOptions[ram_origin] = RamOptions(),
    values_per_key: Int = Int(0)
) -> Self
```

- `buffer_origin` (comptime): The source bytes' origin, inferred from the argument.
- `ram_origin` (comptime): The options' borrowed node-id array, inferred from the argument.
- `executor`: The executor the copy fans out over; it also lends its engine.
- `buffer`: Source holding one serialized monolith.
- `ram`: The memory domains to place shards on; the monolith lands whole on the first.
- `values_per_key`: Upper bound on entries sharing one key, which no checkpoint records.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the bytes cannot be decoded.

## load_vram

Copies a checkpoint into a new, mutable index in device memory, with the placement rules of [`load_ram`](#load_ram). Calls `usearch_dense_load_vram`.

```mojo
def load_vram[path_origin: ImmOrigin, vram_origin: ImmOrigin, //](
    executor: Executor,
    path: StringSpan[path_origin],
    vram: VramOptions[vram_origin] = VramOptions(),
    values_per_key: Int = Int(0)
) -> Self
```

- `path_origin` (comptime): The path bytes' origin, inferred from the argument.
- `vram_origin` (comptime): The options' borrowed ordinal array, inferred from the argument.
- `executor`: The executor the upload runs on, one stream per device; it also lends its engine.
- `path`: The manifest of a sharded checkpoint, or a single `.safegraphs` monolith.
- `vram`: The devices to place the parts on.
- `values_per_key`: Upper bound on entries sharing one key, which no checkpoint records.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the checkpoint cannot be read, or a device cannot hold it.

## load_vram_buffer

Copies a monolith from a host or device buffer into a new, mutable index in device memory. Calls `usearch_dense_load_vram_buffer`.

```mojo
def load_vram_buffer[buffer_origin: ImmOrigin, vram_origin: ImmOrigin, //](
    executor: Executor,
    buffer: Span[UInt8, buffer_origin],
    vram: VramOptions[vram_origin] = VramOptions(),
    values_per_key: Int = Int(0)
) -> Self
```

- `buffer_origin` (comptime): The source bytes' origin, inferred from the argument.
- `vram_origin` (comptime): The options' borrowed ordinal array, inferred from the argument.
- `executor`: The executor the upload runs on, one stream per device; it also lends its engine.
- `buffer`: Source holding one serialized monolith.
- `vram`: The devices to place shards on; the monolith lands whole on the first.
- `values_per_key`: Upper bound on entries sharing one key, which no checkpoint records.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the bytes cannot be decoded, or a device cannot hold them.

## view_ram

Serves a checkpoint in place through a memory mapping, as a read-only index. Calls `usearch_dense_view_ram`.

```mojo
def view_ram[path_origin: ImmOrigin, //](library: Library, path: StringSpan[path_origin]) -> Self
```

Nothing is copied, so opening costs the headers alone. Every mutating verb on the handle
raises with [`READ_ONLY`](https://www.unum.cloud/docs/usearch/mojo/errors.md#READ_ONLY), and the files must stay unmodified until the handle is released.

- `path_origin` (comptime): The path bytes' origin, inferred from the argument.
- `library`: The loaded engine, kept so the shared object stays mapped.
- `path`: The manifest of a sharded checkpoint, or a single `.safegraphs` monolith.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the checkpoint cannot be mapped or decoded.

## view_nvme

Serves a checkpoint in place from NVMe drives, read through the executor's rings. Calls `usearch_dense_view_nvme`.

```mojo
def view_nvme[path_origin: ImmOrigin, nvme_origin: ImmOrigin, //](
    executor: Executor,
    path: StringSpan[path_origin],
    nvme: NvmeOptions[nvme_origin] = NvmeOptions()
) -> Self
```

- `path_origin` (comptime): The path bytes' origin, inferred from the argument.
- `nvme_origin` (comptime): The options' borrowed path array, inferred from the argument.
- `executor`: The NVMe executor whose rings read the checkpoint's headers; it also lends its engine.
- `path`: The manifest of a sharded checkpoint, or a single `.safegraphs` monolith.
- `nvme`: The devices the parts are served from; naming none serves each where it points.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) with [`UNSUPPORTED`](https://www.unum.cloud/docs/usearch/mojo/errors.md#UNSUPPORTED) until NVMe checkpoints carry keys and a shard wrapper.

## on

The same verbs, blocking on `executor` after every call submitted there before them. Binding-only.

```mojo
def on(ref self, ref executor: Executor) -> DenseIndexOn[origin_of(executor, self)]
```

- `executor`: The executor every verb runs on; its kind must match the handle's residency.

## deferred

The same verbs, each submitted to `executor` and answering a [`Deferred`](https://www.unum.cloud/docs/usearch/mojo/executors.md#Deferred) at once. Binding-only.

```mojo
def deferred(ref self, ref executor: Executor) -> DenseIndexDeferredOn[origin_of(executor, self)]
```

- `executor`: The executor every verb is submitted to; its kind must match the handle's residency.

## cursor

Opens a walk over every entry as stored, its pulls on the calling thread. Calls `usearch_dense_cursor_init`.

```mojo
def cursor(ref self) -> DenseCursor[origin_of(self)]
```

```mojo
def cursor[starts_origin: ImmOrigin, //](
    ref self,
    starts: Span[Key, starts_origin]
) -> DenseCursor[origin_of(self)]
```

Opens a walk from `starts`, its pulls on the calling thread. Calls `usearch_dense_cursor_init`.

Each shard's publication watermark is read as the walk enters that shard, so an entry once
passed is never revisited.

- `starts_origin` (comptime): The start keys' origin, inferred from the argument.
- `starts`: The keys to walk from.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) if the residency has no cursor, as VRAM does not.

## search_stream

Opens a resumable nearest-neighbor stream for one query, its pulls on the calling thread. Calls `usearch_dense_search_stream_init`.

```mojo
def search_stream[query_origin: ImmOrigin, //](
    ref self,
    query: RowsView[query_origin],
    config: DenseSearchStreamInitConfig = DenseSearchStreamInitConfig(expansion_factor=Int(0))
) -> DenseSearchStream[origin_of(query_origin, self)]
```

The stream keeps walk state rather than a thread, so any number may stay open at once.

- `query_origin` (comptime): The query row's origin, inferred from the argument.
- `query`: The single query row; a view of more rows has its first row read.
- `config`: The breadth of the candidates the walk explores.

Raises: [`Error`](https://www.unum.cloud/docs/usearch/mojo/errors.md#Error) with [`UNSUPPORTED`](https://www.unum.cloud/docs/usearch/mojo/errors.md#UNSUPPORTED) while no residency implements the stream.

