# Metrics

> USearch for Go

`import "github.com/unum-cloud/USearch/golang"`

## Distance

Distance is a score between two entries, in the metric of the index that produced it.

```go
type Distance = float64
```

## DenseIndex

DenseIndex is a Vector Search Index over equidimensional dense representations.

```go
type DenseIndex struct {
    DenseIndexOn
    // contains filtered or unexported fields
}
```

A handle may be shared across goroutines. 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.

Its verbs come from the embedded DenseIndexOn and run on the calling goroutine; On runs the same
verbs blocking on an executor, and Deferred submits them there.

## DenseInitRam

DenseInitRam creates an empty, mutable index in host memory, one shard per NUMA node memoryDomains names; empty derives every node the process may use.

```go
func DenseInitRam(
    options DenseOptions,
    memoryDomains []int32,
) (*DenseIndex, error)
```

## DenseInitVram

DenseInitVram creates an empty, mutable index in device memory, sharded across the CUDA ordinals devices names and never replicated; empty derives one free device.

```go
func DenseInitVram(
    options DenseOptions,
    devices []int32,
) (*DenseIndex, error)
```

## DenseLoadRam

DenseLoadRam copies a checkpoint into a new, mutable index in host memory.

```go
func DenseLoadRam(
    path string,
    config *DenseLoadRamConfig,
) (*DenseIndex, error)
```

The path names a manifest of a sharded checkpoint or a single .safegraphs monolith.

## DenseLoadRamBuffer

DenseLoadRamBuffer copies a monolith from a buffer into a new, mutable index in host memory, as DenseLoadRam does a path.

```go
func DenseLoadRamBuffer(
    buffer []byte,
    config *DenseLoadRamBufferConfig,
) (*DenseIndex, error)
```

## DenseLoadVram

DenseLoadVram copies a checkpoint into a new, mutable index in device memory, with the placement rules of DenseLoadRam.

```go
func DenseLoadVram(
    path string,
    config *DenseLoadVramConfig,
) (*DenseIndex, error)
```

## DenseLoadVramBuffer

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

```go
func DenseLoadVramBuffer(
    buffer []byte,
    config *DenseLoadVramBufferConfig,
) (*DenseIndex, error)
```

## DenseViewNvme

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

```go
func DenseViewNvme(
    path string,
    config *DenseViewNvmeConfig,
) (*DenseIndex, error)
```

Until NVMe checkpoints carry keys, it reports StatusUnsupported.

## DenseViewRam

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

```go
func DenseViewRam(path string) (*DenseIndex, error)
```

## Close

Close releases the index, waiting for every deferred call naming it.

```go
func (index *DenseIndex) Close() error
```

It is idempotent, and a closed handle must not be used again.

## Deferred

Deferred is the receiver whose verbs submit their calls to executor, each answering a Deferred from the same arguments.

```go
func (index *DenseIndex) Deferred(
    executor *Executor,
) DenseIndexDeferredOn
```

Binding-only.

## On

On is the receiver whose verbs block on executor, after the calls submitted there before them.

```go
func (index *DenseIndex) On(executor *Executor) DenseIndexOn
```

Binding-only.

## Absorb

Absorb moves every donor into this index, one after another, keeping their graphs rather than re-inserting their vectors: each donor's entries append shard by shard, then a refinement links them across the appended part.

```go
func (on DenseIndex) Absorb(
    donors []*DenseIndex,
    config *DenseAbsorbConfig,
) (DenseRefineReport, error)
```

Donors must share the index's residency, scalar, metric and geometry. Readers of a RAM index keep searching throughout; a VRAM one admits no overlapping search.

Each absorbed donor is consumed, and every later verb on it reports StatusUninitialized. A stop
between donors, or a failure, leaves every donor not yet absorbed a live handle the caller still
owns and closes; until the call is final every donor reports StatusUninitialized.

## Attend

Attend is softmax attention of every query row over every indexed key its walk scores, folded as Flash Attention folds key tiles, with no top-k cut, writing one row per query into arena, already divided by the partition.

```go
func (on DenseIndex) Attend(
    queries RowsView,
    lookup ValueLookup,
    arena *Arena,
    config *DenseAttendConfig,
) (DenseVectors, error)
```

The index holds one layer's keys for one key-value head and no values, so lookup resolves every
scored key to its value row. Runs on an inner-product index alone, since a softmax needs logits,
and on RAM and NVMe handles, since a VRAM walk needs a device lookup no Go function can be.

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

## Clear

Clear erases all entries, keeping the reserved capacity and the frozen geometry.

```go
func (on DenseIndex) Clear() error
```

No other verb may overlap it on the same handle.

## Contains

Contains reports whether the index holds at least one entry under a key, as a nonzero Count.

```go
func (on DenseIndex) Contains(key Key) (bool, error)
```

## Count

Count reports how many entries are stored under a key; zero means the index holds none.

```go
func (on DenseIndex) Count(key Key) (uint, error)
```

## Cursor

Cursor opens a walk over the current contents.

```go
func (on DenseIndex) Cursor(starts ...Key) (*DenseCursor, error)
```

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.

## Describe

Describe reports the frozen metadata and the current counters in one call.

```go
func (on DenseIndex) Describe() (DenseIndexDescription, error)
```

## Get

Get exports every vector stored under a key into arena, one row per entry sharing the key, in insertion order, converted to the outputsScalar kind - one call, however many there turn out to be.

```go
func (on DenseIndex) Get(
    key Key,
    outputsScalar Scalar,
    arena *Arena,
) (DenseVectors, error)
```

The call rewinds arena, and the rows stay readable until it serves another call.

## Health

Health audits how much of the graph a search reaches: forward reachability from as many landmarks as one search draws, swept level by level.

```go
func (on DenseIndex) Health() (DenseReachability, error)
```

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

## Insert

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

```go
func (on DenseIndex) Insert(
    keys []Key,
    vectors RowsView,
    config *DenseInsertConfig,
) error
```

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 becomes visible at once, since every fallible step runs before
the first entry identity is claimed. A VRAM call that fails after its first launch publishes
none of its entries, and leaves the handle refusing every later mutation.

## Maxsim

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

```go
func (on DenseIndex) Maxsim(
    queries RowsView,
    rowsPerQuery, wanted uint,
    arena *Arena,
    config *DenseMaxsimConfig,
) (DenseProducts, error)
```

A document is one key holding its token rows, which is what ValuesPerKey above one exists
for. rowsPerQuery is the token count each query occupies, queries holds them end to end, and
wanted counts documents rather than rows, zero keeping every key a query scored. Each query's
keys land in arena as one run, largest score first. Runs on an inner-product index alone.

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

## Multiply

Multiply is the approximate sparse product of a matrix against the indexed vectors - the linear algebra sibling of Search, reporting every pair the traversal scored rather than only the nearest.

```go
func (on DenseIndex) Multiply(
    left RowsView,
    arena *Arena,
    config *DenseMultiplyConfig,
) (DenseProducts, error)
```

Pairs arrive in traversal order rather than sorted, and the pairs the walk never reaches are the low and negative products. Runs on an inner-product index alone.

How many pairs a walk scores is known only once it finishes, so the products, keys and offsets
land in arena, as Get's rows do.

## Refine

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

```go
func (on DenseIndex) Refine(
    config *DenseRefineConfig,
) (DenseRefineReport, error)
```

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. Reports the entries re-selected and
changed, so a caller loops until Changed falls below whatever rate they consider settled.

On a RAM handle searches may run throughout; insertions may not. A stop is a time budget
rather than a failure, so it reports no status.

## Reserve

Reserve claims capacity for a number of incoming vectors ahead of insertion.

```go
func (on DenseIndex) Reserve(capacity uint) error
```

The capacity is the desired total, including the current size.

## Sample

Sample draws up to wanted keys around the config's 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; a larger wanted draws a superset.

```go
func (on DenseIndex) Sample(
    wanted uint,
    arena *Arena,
    config *DenseSampleConfig,
) (DenseDraws, error)
```

Only RAM samples yet.

## Save

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

```go
func (on DenseIndex) Save(
    path string,
    config *DenseSaveConfig,
) error
```

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

## SaveBuffer

SaveBuffer serializes the index as one monolith into arena, a size only the call itself can discover.

```go
func (on DenseIndex) SaveBuffer(
    arena *Arena,
    config *DenseSaveBufferConfig,
) (Monolith, error)
```

## Search

Search resolves a matrix of queries into up to wanted nearest matches apiece, written into arena - the native batch path, parallelized internally, and filtered when the config carries a predicate.

```go
func (on DenseIndex) Search(
    queries RowsView,
    wanted uint,
    arena *Arena,
    config *DenseSearchConfig,
) (MatchesView, error)
```

Never writes to the graph, so any number of these may overlap with concurrent insertions. A
zero wanted walks nothing and lands only the counts, every one zero.

## SearchStream

SearchStream opens a resumable search for a one-row query, so callers that post-filter aggressively pull until satisfied instead of guessing the wanted count upfront.

```go
func (on DenseIndex) SearchStream(
    query RowsView,
    config *DenseSearchStreamInitConfig,
) (*DenseSearchStream, error)
```

No residency implements the stream yet, so the engine answers StatusUnsupported.

## Split

Split hands this index to the receivers, the inverse of Absorb: graph-local parts keeping their edges, one per receiver, leaving this index empty but live.

```go
func (on DenseIndex) Split(
    receivers []*DenseIndex,
    config *DenseSplitConfig,
) (DenseRefineReport, error)
```

Receivers must be empty and share the index's residency, scalar, class, metric, geometry and shard count, and a refusal moves nothing.

## DenseMetric

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

```go
type DenseMetric int32
```

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

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

- `DenseMetricUnknown`: DenseMetricUnknown tags a metric the library could not name.
- `DenseMetricInner`: DenseMetricInner is the inner product.
- `DenseMetricAngular`: DenseMetricAngular is the cosine distance.
- `DenseMetricEuclidean`: DenseMetricEuclidean is the L2 distance.
- `DenseMetricHamming`: DenseMetricHamming counts differing bits.
- `DenseMetricJaccard`: DenseMetricJaccard is the bit-level Jaccard distance.

## String

String renders the metric as the library spells it.

```go
func (metric DenseMetric) String() string
```

## DenseOptions

DenseOptions holds the construction options of a dense index, the fields DenseInitRam and DenseInitVram share.

```go
type DenseOptions struct {
    Dimensions uint
    Metric DenseMetric
    Quantization Scalar
    Connectivity uint
    ValuesPerKey uint
    CPUClass CPUClass
    GPUClass GPUClass
}
```

- `Dimensions` `uint`: Dimensions is the width of the indexed vectors; zero leaves the geometry unfrozen, so the index admits no entries.
- `Metric` `DenseMetric`: Metric is the distance kind used between vectors.
- `Quantization` `Scalar`: Quantization is the scalar type vectors are stored and quantized into.
- `Connectivity` `uint`: Connectivity bounds the connections per node in the graph; zero derives.
- `ValuesPerKey` `uint`: ValuesPerKey bounds how many entries may share one key; zero is unbounded. Above one is what late interaction needs, a document being one key holding its token rows.
- `CPUClass` `CPUClass`: CPUClass is the class a host index dispatches as; the zero value derives the CPU's own.
- `GPUClass` `GPUClass`: GPUClass is the class a device index dispatches as; the zero value derives the devices' own.

## DefaultDenseOptions

DefaultDenseOptions is an angular bf16 index, with every optional field derived.

```go
func DefaultDenseOptions() DenseOptions
```

