# Metrics

> USearch for Swift

### Dense Indexes

A `DenseIndex` holds equidimensional vectors under keys, and its verbs below take every receiver above.

`import USearch`

## Distance

A score between two entries, in the metric of the index that produced it.

```swift
typealias Distance = Double
```

## DenseMetric

A distance kind supported out of the box, with SIMD kernels dispatched by the machine's capabilities.

```swift
struct DenseMetric
```

All of them derive from a single inner-product kernel with pre-computed
magnitudes; hamming and jaccard are bit-level, over the packed sub-byte kinds.

Arbitrary metrics belong to the baseline tier, which forfeits the SIMD kernel chains and the
magnitude cache both.

Conforms to: `Hashable`, `Sendable`, `CustomStringConvertible`, `Equatable`

## unknown

No kind named - an unset field, refused by every constructor.

```swift
static let unknown: DenseMetric
```

## inner

The inner product.

```swift
static let inner: DenseMetric
```

## angular

The cosine distance.

```swift
static let angular: DenseMetric
```

## euclidean

The L2 distance.

```swift
static let euclidean: DenseMetric
```

## hamming

The count of differing bits.

```swift
static let hamming: DenseMetric
```

## jaccard

The bit-level jaccard distance.

```swift
static let jaccard: DenseMetric
```

## description

The metric rendered as the library spells it.

```swift
var description: String { get }
```

## init

Reads a spelling back, and nil for one no metric carries.

```swift
init?(name: String)
```

## DenseOptions

The construction options of a dense index, as [`initRam`](#initRam) and [`initVram`](#initVram) freeze them.

```swift
struct DenseOptions
```

Stored vectors always round up to the SIMD step quantum, so they stay cache-line aligned and
every kernel runs tail-free; the arena is slightly larger for it, and that is not a knob.

Conforms to: `Sendable`

## dimensions

The width of the indexed vectors; zero leaves the geometry unfrozen, so the index admits no entries.

```swift
var dimensions: Int
```

## metric

The distance kind used between vectors.

```swift
var metric: DenseMetric
```

## quantization

The scalar type vectors are stored and quantized into.

```swift
var quantization: Scalar
```

## connectivity

The bound on connections per node in the graph; zero derives.

```swift
var connectivity: Int
```

## valuesPerKey

The bound on entries sharing one key; zero is unbounded.

```swift
var valuesPerKey: Int
```

## cpuClass

The class a host index dispatches as; nil derives the CPU's own.

```swift
var cpuClass: CPUClass?
```

## gpuClass

The class a device index dispatches as; nil derives the devices' own.

```swift
var gpuClass: GPUClass?
```

## init

An angular bf16 index, with every optional field derived.

```swift
init(dimensions: Int = 0, metric: DenseMetric = .angular, quantization: Scalar = .bf16, connectivity: Int = 0, valuesPerKey: Int = 0, cpuClass: CPUClass? = nil, gpuClass: GPUClass? = nil)
```

## DenseIndex

A Vector Search Index over equidimensional dense representations.

```swift
final class DenseIndex
```

A handle may be shared across threads, so no method here takes a lock. 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.

Every verb called on the index runs on the calling thread and blocks until its outcome is
final; `on(_:)` runs the same verbs on an executor, and `deferred(_:)` submits them there.

Conforms to: `Sendable`

## initRam

Initializes an empty, mutable index in host memory, one shard per memory domain; an empty list derives every node the process may allocate on.

```swift
static func initRam(
    _ options: DenseOptions,
    memoryDomains: [Int32] = []
) throws(USearchError) -> DenseIndex
```

## initVram

Initializes an empty, mutable index in device memory, sharded across the named devices and never replicated; an empty list derives one free device.

```swift
static func initVram(
    _ options: DenseOptions,
    devices: [Int32] = []
) throws(USearchError) -> DenseIndex
```

## loadRam

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

```swift
static func loadRam(
    _ path: String,
    config: DenseLoadRamConfig = DenseLoadRamConfig()
) throws(USearchError) -> DenseIndex
```

The geometry and metric come
from the checkpoint's own headers, and part `p` lands whole on shard `p` modulo the shard
count, wherever it was written from.

A cancelled or failed load creates no index.

## loadVram

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

```swift
static func loadVram(
    _ path: String,
    config: DenseLoadVramConfig = DenseLoadVramConfig()
) throws(USearchError) -> DenseIndex
```

## loadRamBuffer

Copies a monolith from a buffer into a new index in host memory, as [`loadRam`](#loadRam) does a path.

```swift
static func loadRamBuffer(
    _ buffer: RawSpan,
    config: DenseLoadRamBufferConfig = DenseLoadRamBufferConfig()
) throws(USearchError) -> DenseIndex
```

## loadVramBuffer

Copies a monolith from a buffer into a new index in device memory, as [`loadVram`](#loadVram) does a path.

```swift
static func loadVramBuffer(
    _ buffer: RawSpan,
    config: DenseLoadVramBufferConfig = DenseLoadVramBufferConfig()
) throws(USearchError) -> DenseIndex
```

## viewRam

Serves a checkpoint in place through a memory mapping, as a read-only index whose mutating verbs report [`readOnly`](https://www.unum.cloud/docs/usearch/swift/errors.md#readOnly); the files must stay unmodified while it lives.

```swift
static func viewRam(_ path: String) throws(USearchError) -> DenseIndex
```

## viewNvme

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

```swift
static func viewNvme(
    _ path: String,
    config: DenseViewNvmeConfig = DenseViewNvmeConfig()
) throws(USearchError) -> DenseIndex
```

Until NVMe checkpoints carry keys, it reports [`unsupported`](https://www.unum.cloud/docs/usearch/swift/errors.md#unsupported).

## metadataRead

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

```swift
static func metadataRead(
    _ path: String,
    executor: Executor? = nil
) throws(USearchError) -> DenseMetadata
```

## metadataReadBuffer

Reads geometry and metric metadata from a serialized monolith buffer.

```swift
static func metadataReadBuffer(
    _ buffer: RawSpan,
    executor: Executor? = nil
) throws(USearchError) -> DenseMetadata
```

## on

The same verbs, blocking on [`executor`](https://www.unum.cloud/docs/usearch/swift/serialization.md#executor) after every call submitted there before them.

```swift
func on(_ executor: Executor) -> DenseIndexOn
```

Binding-only: names the executor every call passes.

## deferred

The same verbs, submitted to [`executor`](https://www.unum.cloud/docs/usearch/swift/serialization.md#executor) and answered at once as a [`Deferred`](https://www.unum.cloud/docs/usearch/swift/executors.md#Deferred).

```swift
func deferred(_ executor: Executor) -> DenseIndexDeferredOn
```

Binding-only:
names the executor and the deferred completion every call passes.

## reserve

Reserves capacity for a total number of entries, the current size included.

```swift
func reserve(_ capacity: Int) throws(USearchError)
```

## clear

Erases all entries, keeping the reserved capacity and the frozen geometry.

```swift
func clear() throws(USearchError)
```

## describe

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

```swift
func describe() throws(USearchError) -> DenseIndexDescription
```

## count

The number of entries stored under a key; zero means the index holds none.

```swift
func count(key: Key) throws(USearchError) -> Int
```

## contains

Whether the index holds at least one entry under a key.

```swift
func contains(key: Key) throws(USearchError) -> Bool
```

Binding-only: calls [`count`](https://www.unum.cloud/docs/usearch/swift/retrieval-and-streaming.md#count).

## get

Retrieves every vector stored under a key, one row per entry sharing the key, in insertion order, converted to `Value`; an absent key yields no rows.

```swift
func get<Value>(
    key: Key,
    as value: Value.Type,
    arena: Arena
) throws(USearchError) -> DenseVectors<Value> where Value : ScalarValue
```

The rows land in `arena`, read in
place by the result until the arena's next call.

## insert

Inserts rows of vectors under their keys - the native batch operation, where a single vector is a one-row matrix.

```swift
func insert(
    keys: [Key],
    vectors: RowsView,
    config: DenseInsertConfig = DenseInsertConfig()
) throws(USearchError)
```

Overlaps safely with concurrent searches on the same handle.

The input scalar type is independent of the stored quantization; the library converts on
ingest. A batch is all-or-nothing, and its entries become visible at once: every fallible step
runs before the first entry identity is claimed, so a thrown failure leaves the index
untouched. Every entry is claimed before the handler's first report, so it reports but cannot
cancel.

## refine

Re-selects the neighbors of every stored entry against the finished graph, reporting the entries re-selected and changed and the islands healed; zero [`changed`](https://www.unum.cloud/docs/usearch/swift/refinement.md#changed) means settled.

```swift
@discardableResult func refine(
    config: DenseRefineConfig = DenseRefineConfig()
) throws(USearchError) -> DenseRefineReport
```

A build step rather than a repair: a cheap insertion pass followed by one refinement
reaches a better graph, in less total time, than one expensive insertion pass - so a wide
expansion factor belongs here rather than in [`insert`](#insert). Searches may run throughout.

## health

Audits how much of the graph a search can reach from its landmarks; entries it misses stay unfound until a refinement re-links them.

```swift
func health() throws(USearchError) -> DenseReachability
```

## search

Resolves rows of queries into up to [`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) matches apiece, written in `arena` - the native batch operation, parallelized internally on an executor.

```swift
func search(
    _ queries: RowsView,
    wanted: Int,
    arena: Arena,
    config: DenseSearchConfig = DenseSearchConfig()
) throws(USearchError) -> Matches
```

The result reads the arena in place
until its next call. Never writes to the graph, so any number of these may overlap with
concurrent insertions.

## maxsim

Late-interaction scoring of multi-row queries against multi-vector documents: every query row takes its best match within a key, and those maxima sum to that key's score.

```swift
func maxsim(
    _ queries: RowsView,
    rowsPerQuery: Int,
    wanted: Int,
    arena: Arena,
    config: DenseMaxsimConfig = DenseMaxsimConfig()
) throws(USearchError) -> DenseProducts
```

A document is one key holding its token rows, which is what a [`valuesPerKey`](https://www.unum.cloud/docs/usearch/swift/serialization.md#valuesPerKey) above one
exists for. `rowsPerQuery` is the token count each query occupies, `queries` holds them end
to end, and up to [`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) documents land in `arena` as one ragged run, one run per whole
query rather than per token, largest score first; a zero [`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) keeps every document the
query scored. Approximate downward only: a token whose neighborhood the walk never entered
contributes no maximum, so a key can score below its exact value but never above it. Runs on
an inner-product index alone.

See [https://arxiv.org/abs/2004.12832](https://arxiv.org/abs/2004.12832) - ColBERT, which introduced this scoring.

## multiply

The approximate sparse product of rows against the indexed vectors - the linear-algebra sibling of [`search`](#search), reporting every pair the traversal scored rather than only the nearest of them.

```swift
func multiply(
    _ left: RowsView,
    arena: Arena,
    config: DenseMultiplyConfig = DenseMultiplyConfig()
) throws(USearchError) -> DenseProducts
```

Pairs arrive in traversal order rather than sorted, and carry no duplicates. A non-zero
[`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) keeps the first pairs each row's walk scored, and [`required`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#required) says how many there
were. The keys, products and row offsets land in `arena` as one ragged run. Runs on an
inner-product index alone, since a product needs logits rather than distances.

## 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.

```swift
func attend<Value>(
    _ queries: RowsView,
    lookup: ValueLookup,
    as value: Value.Type,
    arena: Arena,
    config: DenseAttendConfig = DenseAttendConfig()
) throws(USearchError) -> DenseVectors<Value> where Value : ScalarValue
```

Row `t · headCount + h` of `queries`, `outputs` and [`carry`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#carry) is head `h` of token `t`: the
[`headCount`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#headCount) query heads of grouped-query attention share the index's one key-value head and
one walk per token. The index stores no values, so `lookup` resolves the keys of every
scored batch to rows of its values.

The outputs land in `arena` as `Value` rows, and come back divided by the partition. Passing
a [`carry`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#carry) asks for the softmax state, one entry per query row, which folds this branch into
another over the same queries by partial-softmax rescaling. Runs on an inner-product index
alone, and refuses a VRAM one with [`device`](https://www.unum.cloud/docs/usearch/swift/errors.md#device), whose walk needs a device function as its lookup.

See [https://arxiv.org/abs/2205.14135](https://arxiv.org/abs/2205.14135) - Flash Attention, whose recurrence this reuses.

## absorb

Absorbs every donor into this index, keeping their graphs rather than re-inserting their vectors.

```swift
@discardableResult func absorb(
    _ donors: [DenseIndex],
    config: DenseAbsorbConfig = DenseAbsorbConfig()
) throws(USearchError) -> DenseRefineReport
```

Every donor absorbed is consumed, and every later verb on one reports
[`uninitialized`](https://www.unum.cloud/docs/usearch/swift/errors.md#uninitialized); an absorb stopped early hands the rest back to their indexes once final. A
donor named twice refuses with [`invalidArgument`](https://www.unum.cloud/docs/usearch/swift/errors.md#invalidArgument), and the receiver itself with
[`configMismatch`](https://www.unum.cloud/docs/usearch/swift/errors.md#configMismatch), as the library does.

## split

Splits this index into `receivers`, the inverse of [`absorb`](#absorb): graph-local parts keeping their edges, one per receiver, leaving this index empty but live.

```swift
@discardableResult func split(
    into receivers: [DenseIndex],
    config: DenseSplitConfig = DenseSplitConfig()
) throws(USearchError) -> DenseRefineReport
```

Receivers must be empty and
share the index's residency, scalar, class, metric, geometry and shard count, or the call
answers [`configMismatch`](https://www.unum.cloud/docs/usearch/swift/errors.md#configMismatch), and a refusal moves nothing.

## sample

Draws up to [`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) keys around [`config.focus`](https://www.unum.cloud/docs/usearch/swift/retrieval-and-streaming.md#focus), or across the whole index, each hanging from a shown or earlier draw and placed in three dimensions beside the shown ones, written in `arena`; a larger [`wanted`](https://www.unum.cloud/docs/usearch/swift/linear-algebra.md#wanted) draws a superset.

```swift
func sample(
    wanted: Int,
    arena: Arena,
    config: DenseSampleConfig = DenseSampleConfig()
) throws(USearchError) -> DenseDraws
```

Only RAM samples yet.

## save

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

```swift
func save(path: String, config: DenseSaveConfig = DenseSaveConfig()) throws(USearchError)
```

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

## saveBuffer

Writes the index as one monolith, the same bytes `save(path:)` writes to a `.safegraphs` path, into `arena`.

```swift
func saveBuffer(
    arena: Arena,
    config: DenseSaveBufferConfig = DenseSaveBufferConfig()
) throws(USearchError) -> Monolith
```

## cursor

Opens a walk over the current contents, for export or migration.

```swift
func cursor(starts: [Key] = []) throws(USearchError) -> DenseCursor
```

Each shard's publication
watermark is read as the walk enters it, so an entry once passed is never revisited. 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.

## searchStream

Opens a resumable nearest-neighbor stream over one query row, so a caller that post-filters aggressively pulls until satisfied rather than guessing a wanted count upfront.

```swift
func searchStream(
    _ query: RowsView,
    config: DenseSearchStreamInitConfig = DenseSearchStreamInitConfig()
) throws(USearchError) -> DenseSearchStream
```

